RabbitMq and .net core

I would like to show how to use RabbitMQ and .NET Core. So, I prepared example email queue to send emails.

I want to make a simple email queue. I send email body to queue (by client) and get, parse and send it to recipient (by sender). It’s very useful when have a lot emails to send. But if you want to use my solution you should improve it 😉

I use Ubuntu 16.04

What RabbitMQ is?

As you can find on Wikipedia:

RabbitMQ is open source message broker software (sometimes called message-oriented middleware) that implements the Advanced Message Queuing Protocol (AMQP).

You can find useful links about RabbitMQ below:

  1. http://www.rabbitmq.com/getstarted.html
  2. https://www.rabbitmq.com/install-debian.html (instalation RabbitMQ on Ubuntu)
  3. http://monkeyhacks.com/post/installing-rabbitmq-on-ubuntu-14-04 (instalation RabbitMQ on Ubuntu)
  4. https://www.rabbitmq.com/configure.html (configration)
  5. https://www.rabbitmq.com/dotnet-api-guide.html (.net client for RabbitMQ)

You need to install RabbitMQ on your machine and I don’t show how to do it because of you can find this on 2th and 3rd link.

Project

Complete source code is on github: https://github.com/letyshub/EmailRabbitMq

EmailRabbitMq.Client

Client send email’s details to queue. We use RabbitMQ.Client to connect to RabbitMQ and Newtonsoft.Json to serialize/deserialize our emails. So, we need to add them to project.json:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.1": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.1.0"
        },
        "RabbitMQ.Client": "*",
        "EmailRabbitMq.Shared": "*",
        "Newtonsoft.Json": "*"
      },
      "imports": "dnxcore50"
    }
  }
}

Our sender is simple console application and looks like below:
using System;
using System.Text;
using RabbitMQ.Client;
using EmailRabbitMq.Shared;
using Newtonsoft.Json;

namespace EmailRabbitMq.Client
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var factory = new ConnectionFactory() { HostName = "localhost", UserName = "guest", Password = "guest" };
        
            using(var connection = factory.CreateConnection())
            using(var channel = connection.CreateModel())
            {
                channel.QueueDeclare(queue: "email_queue",
                                     durable: true,
                                     exclusive: false,
                                     autoDelete: false,
                                     arguments: null);

                EmailQueueMessage message = new EmailQueueMessage
                {
                    RecipientEmail = "test@test-email.com",
                    RecipientName = "Test",
                    SenderName = "Rocky Balboa",
                    SenderEmail = "rocky.balboa@test-email.com",
                    Subject = "Test"
                };

                string json = JsonConvert.SerializeObject(message);
                var body = Encoding.UTF8.GetBytes(json);

                channel.BasicPublish(exchange: "",
                                     routingKey: "email_queue",
                                     basicProperties: null,
                                     body: body);
                Console.WriteLine("Sent email: {0}", json);
            }
        }
    }
}

EmailRabbitMq.Sender

To send email we need RabbitMQ.Client and Newtonsoft.Json also. We use MailKit to send email. So, we need to add them to project.json:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true
  },
  "dependencies": {},
  "frameworks": {
    "netcoreapp1.1": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.1.0"
        },
        "Microsoft.Extensions.Configuration": "*",
        "Microsoft.Extensions.Configuration.Json": "*",
        "RabbitMQ.Client": "*",
        "EmailRabbitMq.Shared": "*",
        "Newtonsoft.Json": "*",
        "MailKit" : "*"
      },
      "imports": "dnxcore50"
    }
  }
}

EmailSender class sends emails:
using EmailRabbitMq.Shared;
using MailKit.Net.Smtp;
using MimeKit;

namespace EmailRabbitMq.Sender
{
    public class EmailSender
    {
        private string smtpServer;
        private int port;
        private string user;
        private string password;

        public EmailSender(string smtpServer, string port, string user, string password)
        {
            this.smtpServer = smtpServer;
            this.port = int.Parse(port);
            this.user = user;
            this.password = password;
        }

        public void Send(EmailQueueMessage message)
        {
            var mimeMessage = new MimeMessage();
            mimeMessage.From.Add(new MailboxAddress(message.SenderName, message.SenderEmail));
            mimeMessage.To.Add(new MailboxAddress(message.RecipientName, message.RecipientEmail));
            mimeMessage.Subject = message.Subject;
            mimeMessage.Body = new TextPart("plain")
            {
                Text = message.Body
            };

            using (var client = new SmtpClient())
            {
                client.Connect(this.smtpServer, this.port, false);
                client.Authenticate(this.user, this.password);
                client.Send(mimeMessage);
                client.Disconnect(true);
            }
        }
    }
}

We also use console application to get email from queue and send it.
using System;
using System.Text;
using Newtonsoft.Json;
using RabbitMQ.Client;
using EmailRabbitMq.Shared;
using Microsoft.Extensions.Configuration;
using System.IO;

namespace EmailRabbitMq.Sender
{ 
    public class Program
    {
        public static void Main(string[] args)
        {
            EmailSender sender = CreateEmailSender();

            var factory = new ConnectionFactory() { HostName = "localhost", UserName = "guest", Password = "guest" };

            using (var connection = factory.CreateConnection())
            using (var channel = connection.CreateModel())
            {
                channel.QueueDeclare(queue: "email_queue",
                                     durable: true,
                                     exclusive: false,
                                     autoDelete: false,
                                     arguments: null);

                BasicGetResult result = channel.BasicGet("email_queue", true);
                
                while (result != null)
                {
                    var json = Encoding.UTF8.GetString(result.Body);
                    var msg = JsonConvert.DeserializeObject<EmailQueueMessage>(json);

                    Console.WriteLine("Email from queue:");
                    Console.WriteLine(json);

                    sender.Send(msg);

                    result = channel.BasicGet("email_queue", true);
                }
            }
        }

        public static EmailSender CreateEmailSender()
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json");

            IConfigurationRoot config = builder.Build();

            return new EmailSender(config["server"], config["port"], config["user"], config["password"]);
        }
    }
}

We need also settings to smtp server. We use appsettings.json:
{
  "server": "",
  "port": "123",
  "user": "",
  "password": ""
}

EmailRabbitMq.Shared

This library contains only EmailQueueMessage class. We use it in EmailRabbitMq.Client and EmailRabbitMq.Sender.

namespace EmailRabbitMq.Shared
{
    public class EmailQueueMessage
    {
        public string RecipientEmail { get; set; }
        public string RecipientName { get; set; }
        public string SenderName { get; set; }
        public string SenderEmail { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
    }
}

We create .net core class library by:
[bash]
dotnet new -t lib
[/bash]

Example

To get all packages:
[bash]
dotnet restore
[/bash]
To run project:
[bash]
dotnet run
[/bash]
This is example of sending emails from queue:

This is our messages on queue:

This is example of getting messages from queue: