I am trying to implement the Gmail API into an API application. I created a service account and saved the p12 key and the json credentials. I am getting an exception talking about a failed precondition. I think it might have something to do with the message I'm trying to send.
String serviceAccountEmail = "SERVICE-ACC-EMAIL";
X509Certificate2 certificate = new X509Certificate2("./key.p12", "notasecret", X509KeyStorageFlags.Exportable);
// FileStream stream = new FileStream("./credentials.json", FileMode.Open, FileAccess.Read); // ! Not Used
ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
User = serviceAccountEmail,
Scopes = new[] { GmailService.Scope.MailGoogleCom }
}.FromCertificate(certificate));
GmailService service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Testing Application",
});
var result = service.Users.Messages.Send(CreateEmail.CreateEmailMessage(), "me").Execute();
An unhandled exception of type 'Google.GoogleApiException' occurred in System.Private.CoreLib.dll: 'Google.Apis.Requests.RequestError
Precondition check failed. [400]
Errors [
Message[Precondition check failed.] Location[ - ] Reason[failedPrecondition] Domain[global]
]'
In the CreateEmail.CreateEmailMessage method I build up a new instance of Google.Apis.Gmail.v1.Data.Message. Setting the payload and headers. Take this as reference. I am not sure if this is the way to do it but I can't seem to find a way to create a new message. All I can find is things written in Java or Python which i tried translating over to C#, failing spectacularly
var msg2 = new Message()
{
Payload = new MessagePart()
{
Body = new MessagePartBody()
{
Data = Convert.ToBase64String(Encoding.UTF8.GetBytes("Hello world"))
},
Headers = new List<MessagePartHeader>() {
new MessagePartHeader() { Name = "To", Value = "My email"},
...
Precondition check failed. [400]
with the Gmail api and service accounts normally means that you have not properly setup domain wide delegation to the service account.
Implementing Server-Side Authorization
In your case it may be because you are delegating to a user that is not on your domain.
User = serviceAccountEmail,
Is not the service accounts email address it is the user on your Google Workspace which you want the service account to be impresontating.
string ApplicationName = "Gmail API .NET Quickstart";
const string serviceAccount = "clawskeyboard-smtp@clawskeyboard-api.iam.gserviceaccount.com";
var certificate = new X509Certificate2(@"D:\api-ed4859a67674.p12", "notasecret", X509KeyStorageFlags.Exportable);
var gsuiteUser = "xxx@YourWorkGroupDomain.com";
var serviceAccountCredentialInitializer = new ServiceAccountCredential.Initializer(serviceAccount)
{
User = gsuiteUser,
Scopes = new[] { GmailService.Scope.GmailSend, GmailService.Scope.GmailLabels }
}.FromCertificate(certificate);