0

I was originally using AWS SES for mail sending from my Lambda, but it has very slow delivery.

I then decided to switch to MailJet and use their API for sending mails. I am using the NuGet package, V3.1 of the API, and pretty much the sample code from MailJet to send the mails async.

    public async Task<bool> SendEmailAsync(EmailModel model)
    {            
        Boolean sent = false;

        MailjetClient client = new MailjetClient(Environment.GetEnvironmentVariable("EmailAPIKey"), Environment.GetEnvironmentVariable("EmailAPISecret"))
        {
            Version = ApiVersion.V3_1,
        };

        MailjetRequest request = new MailjetRequest
        {
            Resource = Send.Resource,
        }.Property(Send.Messages, new JArray {
             new JObject {
                 {"From", new JObject {
                         {"Email", Environment.GetEnvironmentVariable("SenderEmail")},
                         {"Name", Environment.GetEnvironmentVariable("SenderEmailName")}
                     }
                 },
                 {"HTMLPart", model.EmailHtmlBody},
                 {"Subject", model.EmailSubject},
                 {"TextPart", model.EmailTextBody},
                 {"To", new JArray {
                     new JObject {
                         {"Email", model.EmailTo},
                         {"Name", model.EmailTo}
                     }
                 }}
             }
            });

        try
        {
            MailjetResponse response = await client.PostAsync(request);

            if (response.IsSuccessStatusCode)
            {
                sent = true;
                LambdaLogger.Log(string.Format("Total: {0}, Count: {1}\n", response.GetTotal(), response.GetCount()));
                LambdaLogger.Log(response.GetData().ToString());
            }
            else
            {
                sent = false;
                LambdaLogger.Log(string.Format("StatusCode: {0}\n", response.StatusCode));
                LambdaLogger.Log(string.Format("ErrorInfo: {0}\n", response.GetErrorInfo()));
                LambdaLogger.Log(response.GetData().ToString());
                LambdaLogger.Log(string.Format("ErrorMessage: {0}\n", response.GetErrorMessage()));
            }
        }
        catch (Exception mailFail)
        {
            sent = false;
            LambdaLogger.Log(string.Format("Failed: {0}\n", mailFail.Message.ToString() + " : " + mailFail.InnerException.Message.ToString()));
        }
   
        return sent;
    }

When I test the code locally everything works just fine.

When I deploy the lambda to AWS and call the method for sending mails, it is completely random if the mail is send. I am guessing it is the async part which fails for some reason, I am hoping someone can help me to figure this out, because for now I am stuck on this issue.

Or if someone can tell me how to get Amazon SES to send without delay.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
JDcode
  • 57
  • 1
  • 5
  • The second line of code looks like it has a syntax error? Aside from that, what are the specifics of how this fails? Don't "guess it is the async part", unless there's a specific observation to indicate that? Is the response from MailJet successful but the email is just never received? The code shown doesn't check the response like [the vendor's code](https://github.com/mailjet/mailjet-apiv3-dotnet#make-your-first-call) does. Perhaps there's an error you're just not observing? – David Jul 31 '20 at 11:54
  • I have now updated the code part to show the entire async method which works locally, but only sometimes when running in AWS. My best guess is I am doing something wrong with async / await, because it seems like the lambda just keeps running and does not wait for the reply from MailJet. – JDcode Jul 31 '20 at 12:27
  • The `await` keyword is specifically for the purpose of waiting for the result of the operation. (Though I certainly can make no guarantees about the 3rd party library being used or its reliability.) How are you calling `SendEmailAsync`? Are you awaiting its result? Are you awaiting the result of the method which calls it? Etc. Basically, is the async/await structure maintained throughout the application? The problem description so far implies that somewhere you may be invoking an async operation and then forgetting about it. – David Jul 31 '20 at 12:35
  • Your input was very helpful, it made me work my way back and you were right, there was a place where I did not have await. Now everything seems to be running smooth, even with Amazon SES. If you put your input as an answer I will mark it as the correct one. – JDcode Jul 31 '20 at 13:07

1 Answers1

1

From the question:

it is completely random

And from a comment:

it seems like the lambda just keeps running and does not wait for the reply from MailJet

It is sounding like an async/await issue, but probably not where you think. Note that you are correctly awaiting the result of the MailJet operation:

MailjetResponse response = await client.PostAsync(request);

But that's only in this method. This method is of course async:

public async Task<bool> SendEmailAsync(EmailModel model)

When you call this method, do you await it? The method where you call it, that should also be async. Do you await that? Basically, are you "async all the way down"?

It sounds like somewhere in the codebase there's an async operation that's being invoked and then forgotten.

David
  • 208,112
  • 36
  • 198
  • 279