Email - NeoSOFT-Technologies/rest-dot-net-core GitHub Wiki

Description

It’s a best practice to confirm the email of a newly registered event. So, admin should get an email notification whenever an event would be created. To use email service, here we will use SendGrid email service. SendGrid is a cloud-based SMTP provider that allows you to send email without having to maintain email servers, and it is easy to host using Microsoft Azure cloud as well.

NuGet Packages

We need to install SendGrid package from NuGet Package Manager.

Code Snippet

appsettings.json file has specified the values for the FromAddress, the ApiKey, and the FromName as key-value pairs.

 "EmailSettings": {
    "FromAddress": "", //Sender's Email Address
    "ApiKey": "", //ApiKey
    "FromName": "" //Sender's Name
  },

Now, create model classes for Email and EmailSettings at location Core/ProjectName.Application/Models/Mail as below,

public class Email
    {
        public string To { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
    }
public class EmailSettings
    {
        public string ApiKey { get; set; }
        public string FromAddress { get; set; }
        public string FromName { get; set; }
    }

Then create an interface named IEmailService at location Core/ProjectName.Application/Contracts/Infrastructure as below,

public interface IEmailService
    {
        Task<bool> SendEmail(Email email);
    }

Create a service class named EmailService at location Core/Infrastructure/ProjectName.Infrastructure/Mail to implement IEmailService interface

public class EmailService : IEmailService
    {
        public EmailSettings _emailSettings { get; }
        public ILogger<EmailService> _logger { get; }

        public EmailService(IOptions<EmailSettings> mailSettings, ILogger<EmailService> logger)
        {
            _emailSettings = mailSettings.Value;
            _logger = logger;
        }

        public async Task<bool> SendEmail(Email email)
        {
            var client = new SendGridClient(_emailSettings.ApiKey);

            var subject = email.Subject;
            var to = new EmailAddress(email.To);
            var emailBody = email.Body;

            var from = new EmailAddress
            {
                Email = _emailSettings.FromAddress,
                Name = _emailSettings.FromName
            };

            var sendGridMessage = MailHelper.CreateSingleEmail(from, to, subject, emailBody, emailBody);
            var response = await client.SendEmailAsync(sendGridMessage);

            _logger.LogInformation("Email sent");

            if (response.StatusCode == System.Net.HttpStatusCode.Accepted || response.StatusCode == System.Net.HttpStatusCode.OK)
                return true;

            _logger.LogError("Email sending failed");

            return false;
        }
    }

Configure this in InfrastructureServiceRegistration at same location as below,

public static class InfrastructureServiceRegistration
    {
        public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
        {
            services.Configure<EmailSettings>(configuration.GetSection("EmailSettings"));
            services.AddTransient<IEmailService, EmailService>();

            return services;
        }
    }

Then, create a event handler named CreateEventCommandHandler at location Core/ProjectName.Application/Features/Events/Commands/CreateEvent,

public class CreateEventCommandHandler : IRequestHandler<CreateEventCommand, Response<Guid>>
    {
        private readonly IEventRepository _eventRepository;
        private readonly IMapper _mapper;
        private readonly IEmailService _emailService;
        private readonly ILogger<CreateEventCommandHandler> _logger;


        public CreateEventCommandHandler(IMapper mapper, IEventRepository eventRepository, IEmailService emailService, ILogger<CreateEventCommandHandler> logger)
        {
            _mapper = mapper;
            _eventRepository = eventRepository;
            _emailService = emailService;
            _logger = logger;
        }

        public async Task<Response<Guid>> Handle(CreateEventCommand request, CancellationToken cancellationToken)
        {
            var validator = new CreateEventCommandValidator(_eventRepository);
            var validationResult = await validator.ValidateAsync(request);

            if (validationResult.Errors.Count > 0)
                throw new Exceptions.ValidationException(validationResult);

            var @event = _mapper.Map<Event>(request);

            @event = await _eventRepository.AddAsync(@event);

            //Sending email notification to admin address
            var email = new Email() { To = "", Body = $"A new event was created: {request}", Subject = "A new event was created" };

            try
            {
                await _emailService.SendEmail(email);
            }
            catch (Exception ex)
            {
                _logger.LogError($"Mailing about event {@event.EventId} failed due to an error with the mail service: {ex.Message}");
            }

            var response = new Response<Guid>(@event.EventId, "Inserted successfully ");

            return response;
        }
    }

Demo

Demo video to get the clear result view of above implemented module.

Email.mp4
⚠️ **GitHub.com Fallback** ⚠️