A key part of any identity process involves the sending of emails for things like account verification, forgotten password and security updates. Testing these can present several challenges as there are usually 3rd party services involved (you’re unlikely to be including a custom SMTP server and mailbox with your project!)
In the first part of this guide I’m going to show you how you can test emails before they’re sent using a dummy SMTP service.
For the purpose of this guide I’m going to use C# but the services used provide support for multiple languages. Let’s get started:
1. Create a free Mailtrap account
2. Note your API key from your account page
3. Note SMTP details for the provided mailbox
4. Create a new project in Visual Studio – I’m using an NUnit test project for my
examples
5. Using the System.Net.Mail library, send some basic emails for our testing purposes
How you can test emails before they’re sent using a dummy SMTP service
How to use IMAP with Gmail
Why a key part of any identity process involves the sending of emails
smtpClient = new SmtpClient(“smtp.mailtrap.io”, 2525) { Credentials = new NetworkCredential(<smtp_mailbox_username>, <smtp_mailbox_password>), EnableSsl = true }; smtpClient.Send(“from@example.com”, “to@example.com”, “Dummy email 1”, “Email for basic Mailtrap tests”); smtpClient.Send(“from@example.com”, “to@example.com”, “Dummy email 2”, “Email for basic Mailtrap tests”);</smtp_mailbox_password></smtp_mailbox_username>
6. Now that our inbox has some mail, we can query the inbox and the messages within. First, we’ll create some basic entity classes to de-serialise from the JSON response for use in our tests:
I’ve created a sample client app that uses the Mailtrap v1 API. You can grab the source from bitbucket.
public class Inbox { [JsonProperty(“id”)] public int? Id { get; set; } [JsonProperty(“name”)] public string Name { get; set; } [JsonProperty(“emails_count”)] public int MessageCount { get; set; } } public class Message { [JsonProperty(“id”)] public int? Id { get; set; } [JsonProperty(“subject”)] public string Subject { get; set; } [JsonProperty(“sent_at”)] public DateTime SentAt { get; set; } … }
7. In order to see your email messages you’ll first need the inbox ID. This can be grabbed from the Mailtrap UI or you can query the /inboxes resource. I’m using RestSharp along with Newtonsoft.Json:
var client = new RestClient(“https://mailtrap.io/api/v1”); client.AddDefaultHeader(“Api-Token”, <your-api-token>); var request = new RestRequest(“inboxes”); var response = client.Execute(request); var inboxes = JsonConvert.DeserializeObject<ilist<inbox>>(response.Content); Assert.That(inboxes.Count, Is.GreaterThan(0)); Console.WriteLine(inboxes[0].Id);</ilist<inbox></your-api-token>
8. Now that you have an inbox ID, you can query the messages within using the path /inboxes/{id}/messages:
var request = new RestRequest(“inboxes/<inbox_id>/messages”); var response = client.Execute(request); var messages = JsonConvert.DeserializeObject<ilist<message>>(response.Content); Assert.That(messages.Count, Is.GreaterThan(0)); foreach (var message in messages) { Console.WriteLine($”{message.Id} {message.Subject} {message.SentAt}”); }</ilist<message></inbox_id>
9. Finally, you’ll likely want to clean up after yourself. You can use the inbox clean method via /inboxes/{id}/clean, note that this uses the http PATCH method:
var request = new RestRequest(“inboxes/<inbox_id>/clean”, Method.PATCH); var response = client.Execute(request); var inbox = JsonConvert.DeserializeObject<inbox>(response.Content); Assert.That(inbox.MessageCount, Is.EqualTo(0));</inbox></inbox_id>
10. And that’s it, simple access to your SMTP output using Mailtrap! Be sure to check out the API documentation for greater coverage of the available resources and properties available for your testing.
At the beginning of this guide we looked at how we can use Mailtrap.io to intercept our SMTP traffic before our emails are sent out. In this section we’re going to use IMAP to talk to our Gmail account, offering more of an end-to-end test, as well as covering cases where the SUT doesn’t call SMTP directly.
Gmail is great for a number of reasons, it’s free for a start, but a huge benefit for testing is the ability to use a single account with dynamic aliased addresses. You can create my.email@gmail.com and then use my.email+alias01@gmail.com, my.email+alias02@gmail.com etc. Another option is to use a service like Mailinator but this will set you back $1500/year if you want programmatic access via their API.
1. So firstly, get yourself a free account
2. Next, visit the mailbox settings and Enable IMAP on the Forwarding and POP/IMAP tab
3. Now you’ll need to allow less secure apps on the account’s security settings – this lets us authorise our calls with an email/password combo, avoiding OAuth2.0
4. That should be everything that’s needed with the email account, now we need a way to talk to the IMAP service. Once again, I’ll be working in C# with the ImapX library
5. Again, we’ll want to populate our inbox with a few emails – thankfully we can also use Gmail as our SMTP server to post messages
using (var smtpClient = new SmtpClient(“smtp.gmail.com”, 587)) { smtpClient.EnableSsl = true; smtpClient.Credentials = new NetworkCredential(<gmail_account>, <gmail_password>); smtpClient.Send(“from@example.com”, “to@example.com”, “Dummy email 1”, “Email for basic Gmail tests”); smtpClient.Send(“from@example.com”, “to@example.com”, “Dummy email 2”, “Email for basic Gmail tests”); }</gmail_password></gmail_account>
6. Now we can use ImapX to connect to the inbox
imapClient = new ImapClient(“imap.gmail.com”, 993, true); imapClient.Behavior.AutoPopulateFolderMessages = true; imapClient.Connect(); imapClient.Login(<gmail_account>, <gmail_password>);</gmail_password></gmail_account>
7. Accessing our inbox is now simple
var inbox = imapClient.Folders.Inbox; Assert.That(inbox.Exists == 2, “Should be a total of 2 emails as per test setup”);
8. You’ll likely want to search your inbox and this is done by supplying an IMAP search query, these can be strung together e.g. “TO <email> SUBJECT Dummy email 1”</email>
var search = inbox.Search(“SUBJECT Dummy email 1”); Assert.That(search.Length == 1, “Expected a single matching email”); Assert.That(search[0].To[0].Address, Is.EqualTo(“to@example.com”));
9. Finally a little cleanup
So there you have it, programmatic access to a dynamic email address for use in your integration and end to end tests. Again you can find some sample code over in Bitbucket including some interactions with the Google dotnet SDK and S22, an alternative dotnet IMAP client.