क्रिश्चियन शॉ
  • होम
  • Blog
    • प्रोग्रामिंग
      • C#
      • पॉवरशेल
      • Python
      • SQL
    • वर्डप्रेस
      • ट्युटोरियल
    • क्लाउड
    • होम ऑटोमेशन
      • होम असिस्टेंट
        • Node-Red
    • Career
  • सेवाएं
  • शब्दकोष
  • About
No Result
View All Result
क्रिश्चियन शॉ
  • होम
  • Blog
    • प्रोग्रामिंग
      • C#
      • पॉवरशेल
      • Python
      • SQL
    • वर्डप्रेस
      • ट्युटोरियल
    • क्लाउड
    • होम ऑटोमेशन
      • होम असिस्टेंट
        • Node-Red
    • Career
  • सेवाएं
  • शब्दकोष
  • About
No Result
View All Result
क्रिश्चियन शॉ
No Result
View All Result
Home प्रोग्रामिंग C#

How to Send Emails with ASP.NET Core using SMTP with MailKit

by ईसाई
2022-12-मई
in C#
0

I often see the question “how to send emails with ASP.NET Core” and it is also one thing I often implement in the software applications I make or extend. Emails are used for confirmations at user sign-up, new orders, newsletters, OTP (one-time-password) emails, etc… It’s a very common requirement for many applications, which also is one of the reasons I have baked it into the core of my toolbox for new applications.

In this article, I will show you how to send emails with C# / ASP.NET Core using Mailkit. When you are done reading this article you know how to create an ASP.NET Core Web API, add new configuration details and how to implement new logic in order to send emails using MailKit with an SMTP account.

विषय-सूची
  1. Quick F.A.Q about MailKit
    • What is MailKit?
    • What is an SMPT Server?
  2. Requirements
  3. Create an ASP.NET Core Web API from a template
  4. Implement email functionality in ASP.NET Core Web API
    • Install the MailKit package in the project
    • Update appsettings.json to include SMTP- and Email details
    • Read MailSettings from appsettings.json at runtime
    • Add MailKit to send emails with ASP.NET Core
      • Create MailData Model
      • Create an Interface for sending an email with ASP.NET Core
      • Add Logic for sending emails with ASP.NET Core with MailKit
      • Add a new MailController to send emails
      • TESTING – Send Emails with ASP.NET Core Web API
    • Send emails with ASP.NET core including attachment
    • Send emails using templates in ASP.NET Core
      • Install the RazorEngineCore package in the project
      • The HTML Template
      • Create a new model for welcome emails to users
      • Add Email Template Service to the Mail Service
      • Add a new endpoint to generate a Welcome Email to the user
      • Testing the email service for sending mails using HTML templates
  5. Summary

Quick F.A.Q about MailKit

What is MailKit?

MailKit is a cross-platform mail client library built on top of MimeKit. MailKit is a personal open-source project that jstedfast has put thousands of hours into perfecting with the goal of making it the very best email framework for .NET.

What is an SMPT Server?

SMTP is short for Simple Mail Transfer Protocol. If you append “server” to SMTP you get an SMPT Server which is an email-based server that allows you, applications, or other users to send and receive emails between two parties. Gmail, Outlook, Yahoo, etc… are SMTP servers. When you signup for an email account at these services, you get an ID that is capable of sending and receiving emails on that specific SMTP Server.

By default, an SMTP server will have an address that will be consumed by other mail clients like MailKit that we will be using for this article. For this, to work we have to obtain SMTP server details like Host, Port, Security Settings, Username/Password, etc…

Requirements

If you would like to follow along or implement MailKit in your own solution, you will need at least, the following:

  • An IDE (I will be using Visual Studio 2022 Community Edition)
  • .NET 6
  • Access to an Email account (I will be suing Ethereal for this article). Ethereal is a fake SMTP service, where the mail never gets delivered. You can create an account here.
  • Access to the internet 😉

Create an ASP.NET Core Web API from a template

Open Visual Studio and create a new project. I have named mine MailKitDemo and my settings are as below:

create asp.net core web api from template
Create ASP.NET Core Web API Project

Implement email functionality in ASP.NET Core Web API

Now that we got our project in place, let’s move on and implement some logic for sending emails and emails based on templates with the Razor engine.

Install the MailKit package in the project

You can do this in multiple ways. If you like me prefer the CLI, look below for the commands. Else you can right-click your project in the solution explorer and click on Manage NuGet Packages. In the popup window, you click on the Browse tab and search for MailKit. Now install the MailKit package.

install MailKit
Install MailKit in the project

You can check the NuGet package for MailKit here to get the latest version tag.

###
Install-Package MailKit
###
###
dotnet add package MailKit
###
###
<PackageReference Include="MailKit" Version="<Version-Tag-Here>" />
###

Update appsettings.json to include SMTP- and Email details

To send an email we need to provide some SMTP server details along with the account we would like to send emails from. These details should not be hardcoded in the application as they might change over time and needs to be updated. It also makes it easier to maintain for other developers. Below is the implementation in appsettings.json.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "MailSettings": {
    "DisplayName": "Christian Schou",
    "From": "[email protected]",
    "Host": "smtp.ethereal.email",
    "Password": "upPftsKAqgcFKKmX8W",
    "Port": 587,
    "UserName": "[email protected]",
    "UseSSL": false,
    "UseStartTls": true
  }
}

As you can see I am using Ethereal for demo purposes, but you can switch the details with your own SMTP Server- and Account details.

Read MailSettings from appsettings.json at runtime

Now that we have added our details for the configuration inside appsettings.json, we would like to load those settings from the JSON file and make them available to the code at runtime in order to send the emails from our application.

Create a new folder named Configuration at the root of your project and add a new file named MailSettings.cs inside that folder with the properties shown below. Remember to change the namespace if you copy the code.

namespace MailKitDemo.Configuration
{
    public class MailSettings
    {
        public string? DisplayName { get; set; }
        public string? From { get; set; }
        public string? UserName { get; set; }
        public string? Password { get; set; }
        public string? Host { get; set; }
        public int Port { get; set; }
        public bool UseSSL { get; set; }
        public book UseStartTls { get; set; }
    }
}

By using Options Pattern and Dependency Injection we can read the data from the JSON file into our MailSettings class object.

Inside Program.cs you have to add the following line (line 11) of code in order to pick up the settings. What happens here s that we use Configuration to read the data from a specific section named MailSettings just like our class object. The data will then be loaded into the object and made available to controllers and repositories/services through Dependency Injection.

using MailKitDemo.Configuration;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.Configure<MailSettings>(builder.Configuration.GetSection(nameof(MailSettings)));

var app = builder.Build();
...

Add MailKit to send emails with ASP.NET Core

Now for the fun part, where we actually implement the core logic for sending emails with ASP.NET Core using SMTP with MailKit.

Create MailData Model

The first thing we have to do is add a model that will hold all of our basic mail data. Create a new folder named Models at the root of your project and create a new file named MailData.cs with the following properties inside.

namespace MailKitDemo.Models
{
    public class MailData
    {
        // Receiver
        public List<string> To { get; }
        public List<string> Bcc { get; }

        public List<string> Cc { get; }

        // Sender
        public string? From { get; }

        public string? DisplayName { get; }

        public string? ReplyTo { get; }

        public string? ReplyToName { get; }

        // Content
        public string Subject { get; }

        public string? Body { get; }

        public MailData(List<string> to, string subject, string? body = null, string? from = null, string? displayName = null, string? replyTo = null, string? replyToName = null, List<string>? bcc = null, List<string>? cc = null)
        {
            // Receiver
            To = to;
            Bcc = bcc ?? new List<string>();
            Cc = cc ?? new List<string>();

            // Sender
            From = from;
            DisplayName = displayName;
            ReplyTo = replyTo;
            ReplyToName = replyToName;
            
            // Content
            Subject = subject;
            Body = body;
        }
    }
}

Create an Interface for sending an email with ASP.NET Core

Now we have to add a new service (interface) for sending the emails using our newly installed MailKit library. Create a new folder named सेवाएं at the root of your project along with two new files inside named ImailService.cs and MailService.cs.

Add the following inside MailService.cs:

using MailKitDemo.Models;

namespace MailKitDemo.Services
{
    public interface IMailService
    {
        Task<bool> SendAsync(MailData mailData, CancellationToken ct);
    }
}

Add Logic for sending emails with ASP.NET Core with MailKit

Below is the implementation for our MailService. I have used the IOption interface in the constructor to inject the MailSettings data object into the service implementation. As you might remember this object contains settings for our SMTP server and the account we are connecting to at the SMTP server.

using MailKit.Net.Smtp;
using MailKit.Security;
using MailKitDemo.Configuration;
using MailKitDemo.Models;
using Microsoft.Extensions.Options;
using MimeKit;

namespace MailKitDemo.Services
{
    public class MailService : IMailService
    {
        private readonly MailSettings _settings;

        public MailService(IOptions<MailSettings> settings)
        {
            _settings = settings.Value;
        }

        public async Task<bool> SendAsync(MailData mailData, CancellationToken ct = default)
        {
            try
            {
                // Initialize a new instance of the MimeKit.MimeMessage class
                var mail = new MimeMessage();

                #region Sender / Receiver
                // Sender
                mail.From.Add(new MailboxAddress(_settings.DisplayName, mailData.From ?? _settings.From));
                mail.Sender = new MailboxAddress(mailData.DisplayName ?? _settings.DisplayName, mailData.From ?? _settings.From);

                // Receiver
                foreach (string mailAddress in mailData.To)
                    mail.To.Add(MailboxAddress.Parse(mailAddress));

                // Set Reply to if specified in mail data
                if(!string.IsNullOrEmpty(mailData.ReplyTo))
                    mail.ReplyTo.Add(new MailboxAddress(mailData.ReplyToName, mailData.ReplyTo));

                // BCC
                // Check if a BCC was supplied in the request
                if (mailData.Bcc != null)
                {
                    // Get only addresses where value is not null or with whitespace. x = value of address
                    foreach (string mailAddress in mailData.Bcc.Where(x => !string.IsNullOrWhiteSpace(x)))
                        mail.Bcc.Add(MailboxAddress.Parse(mailAddress.Trim()));
                }

                // CC
                // Check if a CC address was supplied in the request
                if (mailData.Cc != null)
                {
                    foreach (string mailAddress in mailData.Cc.Where(x => !string.IsNullOrWhiteSpace(x)))
                        mail.Cc.Add(MailboxAddress.Parse(mailAddress.Trim()));
                }
                #endregion

                #region Content

                // Add Content to Mime Message
                var body = new BodyBuilder();
                mail.Subject = mailData.Subject;
                body.HtmlBody = mailData.Body;
                mail.Body = body.ToMessageBody();

                #endregion

                #region Send Mail

                using var smtp = new SmtpClient();

                if (_settings.UseSSL)
                {
                    await smtp.ConnectAsync(_settings.Host, _settings.Port, SecureSocketOptions.SslOnConnect, ct);
                }
                else if (_settings.UseStartTls)
                {
                    await smtp.ConnectAsync(_settings.Host, _settings.Port, SecureSocketOptions.StartTls, ct);
                }
                await smtp.AuthenticateAsync(_settings.UserName, _settings.Password, ct);
                await smtp.SendAsync(mail, ct);
                await smtp.DisconnectAsync(true, ct);
                
                #endregion

                return true;

            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}

All we have to do now is register the service inside our application container in order for us to be able to inject it into the API controller using dependency injection. To add the mail service to the container, we have to register it in Program.cs like I have done below at line 13:

using MailKitDemo.Configuration;
using MailKitDemo.Services;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.Configure<MailSettings>(builder.Configuration.GetSection(nameof(MailSettings)));
builder.Services.AddTransient<IMailService, MailService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Add a new MailController to send emails

The moment we all have been waiting for. Let’s add a new controller named MailController inside the Controllers folder and add a new API endpoint taking a POST request for sending an email using our IMailService we are making it available through dependency injection.

using MailKitDemo.Models;
using MailKitDemo.Services;
using Microsoft.AspNetCore.Mvc;

namespace MailKitDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class MailController : ControllerBase
    {
        private readonly IMailService _mail;

        public MailController(IMailService mail)
        {
            _mail = mail;
        }

        [HttpPost("sendmail")]
        public async Task<IActionResult> SendMailAsync(MailData mailData)
        {
            bool result = await _mail.SendAsync(mailData, new CancellationToken());

            if (result)
            {
                return StatusCode(StatusCodes.Status200OK, "Mail has successfully been sent.");
            } 
            else
            {
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occured. The Mail could not be sent.");
            }
        }
    }
}

In the code above I have added a POST method named SendMailAsync and made it available at host:port/api/sendmail. This takes by default the MailData object but allows nulls in several of the values, meaning that you don’t have to fill all values when posting the data. Let’s spin it up for a test drive and send emails with ASP.NET Core for the first time in this MailKit Demo.

TESTING – Send Emails with ASP.NET Core Web API

I have removed the default controller for the WeatherForecast – we don’t need that controller. Select the action under Mail and fill out the details in the prepared JSON payload. You are free to remove some of the properties as we allow nulls – remember that?

My test payload:

{
  "to": [
    "[email protected]"
  ],
  "displayName": "Christian Schou",
  "replyTo": "[email protected]",
  "replyToName": "Test mail",
  "subject": "Hello World",
  "body": "Hola - this is just a test to verify that our mailing works. Have a great day!"
}

Spin up the project and send a request to the endpoint.

send emails with asp.net core
Test Send Mail API endpoint

Awesome! We have successfully sent an email! Let’s check Ethereal to verify that data has come through correctly.

Ethereal result of test mail
Ethereal Result of Test Mail

Send emails with ASP.NET core including attachment

To add an attachment to our email we have to extend the email service to include logic for that. Open up IMailService and add the following line of code to that interface (line 8).

using MailKitDemo.Models;

namespace MailKitDemo.Services
{
    public interface IMailService
    {
        Task<bool> SendAsync(MailData mailData, CancellationToken ct);
        Task<bool> SendWithAttachmentsAsync(MailDataWithAttachments mailData, CancellationToken ct);
    }
}

Then we are going to add a new the model named MaildataWithAttachments with a IFormFileCollection for the attachments, like below – please notice I am doing it without a constructor in the class this time to show how it also can be done:

namespace MailKitDemo.Models
{
    public class MailDataWithAttachments
    {
        // Receiver
        public List<string>? To { get; set; }
        public List<string>? Bcc { get; set; }
        public List<string>? Cc { get; set; }

        // Sender
        public string? From { get; set; }
        public string? DisplayName { get; set; }
        public string? ReplyTo { get; set; }
        public string? ReplyToName { get; set; }

        // Content
        public string? Subject { get; set; }
        public string? Body { get; set; }
        public IFormFileCollection? Attachments { get; set;  }
    }
}

Then we extend the functionality of our MailService with a new method named SendAsyncWithAttachments(). Take a look at the region Content to see the extra piece of code I have added to send the email with an attachment or multiple attachments (only if the value from the requesting method is not null). Lines to notice: 65-84 as marked below:

using MailKit.Net.Smtp;
using MailKit.Security;
using MailKitDemo.Configuration;
using MailKitDemo.Models;
using Microsoft.Extensions.Options;
using MimeKit;

namespace MailKitDemo.Services
{
    public class MailService : IMailService
    {
        private readonly MailSettings _settings;

        public MailService(IOptions<MailSettings> settings)
        {
            _settings = settings.Value;
        }

        public async Task<bool> SendAsync(MailData mailData, CancellationToken ct = default) 
        {
            try
            {
                // Initialize a new instance of the MimeKit.MimeMessage class
                var mail = new MimeMessage();

                #region Sender / Receiver
                // Sender
                mail.From.Add(new MailboxAddress(_settings.DisplayName, mailData.From ?? _settings.From));
                mail.Sender = new MailboxAddress(mailData.DisplayName ?? _settings.DisplayName, mailData.From ?? _settings.From);

                // Receiver
                foreach (string mailAddress in mailData.To)
                    mail.To.Add(MailboxAddress.Parse(mailAddress));

                // Set Reply to if specified in mail data
                if(!string.IsNullOrEmpty(mailData.ReplyTo))
                    mail.ReplyTo.Add(new MailboxAddress(mailData.ReplyToName, mailData.ReplyTo));

                // BCC
                // Check if a BCC was supplied in the request
                if (mailData.Bcc != null)
                {
                    // Get only addresses where value is not null or with whitespace. x = value of address
                    foreach (string mailAddress in mailData.Bcc.Where(x => !string.IsNullOrWhiteSpace(x)))
                        mail.Bcc.Add(MailboxAddress.Parse(mailAddress.Trim()));
                }

                // CC
                // Check if a CC address was supplied in the request
                if (mailData.Cc != null)
                {
                    foreach (string mailAddress in mailData.Cc.Where(x => !string.IsNullOrWhiteSpace(x)))
                        mail.Cc.Add(MailboxAddress.Parse(mailAddress.Trim()));
                }
                #endregion

                #region Content

                // Add Content to Mime Message
                var body = new BodyBuilder();
                mail.Subject = mailData.Subject;
                body.HtmlBody = mailData.Body;
                mail.Body = body.ToMessageBody();

                // Check if we got any attachments and add the to the builder for our message
                if (mailData.Attachments != null)
                {
                    byte[] attachmentFileByteArray;
                    
                    foreach (IFormFile attachment in mailData.Attachments)
                    {
                        // Check if length of the file in bytes is larger than 0
                        if (attachment.Length > 0)
                        {
                            // Create a new memory stream and attach attachment to mail body
                            using (MemoryStream memoryStream = new MemoryStream())
                            {
                                // Copy the attachment to the stream
                                attachment.CopyTo(memoryStream);
                                attachmentFileByteArray = memoryStream.ToArray();
                            }
                            // Add the attachment from the byte array
                            body.Attachments.Add(attachment.FileName, attachmentFileByteArray, ContentType.Parse(attachment.ContentType));
                        }
                    }
                }

                #endregion

                #region Send Mail

                using var smtp = new SmtpClient();

                if (_settings.UseSSL)
                {
                    await smtp.ConnectAsync(_settings.Host, _settings.Port, SecureSocketOptions.SslOnConnect, ct);
                }
                else if (_settings.UseStartTls)
                {
                    await smtp.ConnectAsync(_settings.Host, _settings.Port, SecureSocketOptions.StartTls, ct);
                }

                await smtp.AuthenticateAsync(_settings.UserName, _settings.Password, ct);
                await smtp.SendAsync(mail, ct);
                await smtp.DisconnectAsync(true, ct);

                return true;
                #endregion

            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}

Finally, we have to wire it up in our MailController to accept a POST request for sending the email with attachment(s). Check the code below for accepting a form defined by the model.

[HttpPost("sendemailwithattachment")]
public async Task<IActionResult> SendMailWithAttachmentAsync([FromForm]MailDataWithAttachments mailData)
{
    bool result = await _mail.SendWithAttachmentsAsync(mailData, new CancellationToken());

    if (result)
    {
        return StatusCode(StatusCodes.Status200OK, "Mail with attachment has successfully been sent.");
    }
    else
    {
        return StatusCode(StatusCodes.Status500InternalServerError, "An error occured. The Mail with attachment could not be sent.");
    }
}

Alright – let’s spin it up and send an email with an attachment and verify that the attachment got through to the receiver.

send email with attachment
Send an email with multiple attachments

The response from the API endpoint when executing that.

send email with attachment
Response from API has been

Cool! We can now send emails with ASP.NET Core including attachments! Let’s verify in our inbox that the mail got through and the attachments are there as well.

ethereal mail with attachments
Ethereal showing mail object with the two attachments

Send emails using templates in ASP.NET Core

An email template comes in very handy if you are going to automate the process of sending emails to users of your application. I tend to always use HTML-based emails unless I am doing some very important status messages for users in my organization, who just prefer a simple text mail.

HTML-based emails are great for greeting new users, sending newsletters, notifications, order confirmations, etc… Now that we got the mailing functionality in place, let’s have a look at how we can send emails using MailKit with ASP.NEt Core. For this, we will make use of the Razor engine and a simple HTML template where we will replace text using models.

If you are ready, let’s get started and create a welcome email for our users. The final result is going to be the one you can see below.

welcome email template
Send Emails using a template with ASP.NET Core

Install the RazorEngineCore package in the project

RazorEngineCore is a NET6 Razor Template Engine. We will use it for modifying our HTML template with data from the model we parse to it.

You can find the package here at nuget.org – RazorEngineCore. Alternatively, you can go to your package manager as we did earlier in this article, and install the package by searching for RazorEngineCore in the browse tab.

###
Install-Package RazorEngineCore
###
###
dotnet add package RazorEngineCore
###
###
<PackageReference Include="RazorEngineCore" Version="<VERSION-TAG-HERE>" />
###
install package, package overview
RazorEngineCore Installed Package

The HTML Template

The template is made of HTML with a little modification for Razor to use it. We are not storing it as a normal HTML file in our project, it has to be saved as a .cshtml file. The template below is taken from BBBootstrap and can be found here Boostrap 4 Confirm Account Email Template.

When working with .cshtml files, we need a way to escape some special characters in the code. In the template below, I have added @("@") in front of all “@“. This is because we need the @ to be there in order to make the styling work.

In the heading, I have added @Model?.Name in the pre-hidden text and after the welcome text. This text will be replaced at runtime using a model in a generic method with RazorEngineCore. You can simply copy and paste the HTML code below and put it in a new file named welcome.cshtml. Place that welcome file in a new folder ./Files/MailTemplates/.

folder structure visual studio 2022
Current Project Structure
<!DOCTYPE html>
<html>

<head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <stylecss">
        @("@")media screen {
            @("@")font-face {
                font-family: 'Lato';
                font-style: normal;
                font-weight: 400;
                src: local('Lato Regular'), local('Lato-Regular'), url(https://fonts.gstatic.com/s/lato/v11/qIIYRU-oROkIk8vfvxw6QvesZW2xOQ-xsNqO47m55DA.woff) format('woff');
            }

            @("@")font-face {
                font-family: 'Lato';
                font-style: normal;
                font-weight: 700;
                src: local('Lato Bold'), local('Lato-Bold'), url(https://fonts.gstatic.com/s/lato/v11/qdgUG4U09HnJwhYI-uK18wLUuEpTyoUstqEm5AMlJo4.woff) format('woff');
            }

            @("@")font-face {
                font-family: 'Lato';
                font-style: italic;
                font-weight: 400;
                src: local('Lato Italic'), local('Lato-Italic'), url(https://fonts.gstatic.com/s/lato/v11/RYyZNoeFgb0l7W3Vu1aSWOvvDin1pK8aKteLpeZ5c0A.woff) format('woff');
            }

            @("@")font-face {
                font-family: 'Lato';
                font-style: italic;
                font-weight: 700;
                src: local('Lato Bold Italic'), local('Lato-BoldItalic'), url(https://fonts.gstatic.com/s/lato/v11/HkF_qI1x_noxlxhrhMQYELO3LdcAZYWl9Si6vvxL-qU.woff) format('woff');
            }
        }

        /* CLIENT-SPECIFIC STYLES */
        body,
        table,
        td,
        a {
            -webkit-text-size-adjust: 100%;
            -ms-text-size-adjust: 100%;
        }

        table,
        td {
            mso-table-lspace: 0pt;
            mso-table-rspace: 0pt;
        }

        img {
            -ms-interpolation-mode: bicubic;
        }

        /* RESET STYLES */
        img {
            border: 0;
            height: auto;
            line-height: 100%;
            outline: none;
            text-decoration: none;
        }

        table {
            border-collapse: collapse !important;
        }

        body {
            height: 100% !important;
            margin: 0 !important;
            padding: 0 !important;
            width: 100% !important;
        }

        /* iOS BLUE LINKS */
        a[x-apple-data-detectors] {
            color: inherit !important;
            text-decoration: none !important;
            font-size: inherit !important;
            font-family: inherit !important;
            font-weight: inherit !important;
            line-height: inherit !important;
        }

        /* MOBILE STYLES */
        @("@")media screen and (max-width:600px) {
            h1 {
                font-size: 32px !important;
                line-height: 32px !important;
            }
        }

        /* ANDROID CENTER FIX */
        div[style*="margin: 16px 0;"] {
            margin: 0 !important;
        }
    </style>
</head>

<body style="background-color: #f4f4f4; margin: 0 !important; padding: 0 !important;">
    <!-- HIDDEN PREHEADER TEXT -->
    <div style="display: none; font-size: 1px; color: #fefefe; line-height: 1px; font-family: 'Lato', Helvetica, Arial, sans-serif; max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden;">@Model?.Name We're thrilled to have you here! Get ready to dive into your new account. </div>
    <table border="0" cellpadding="0" cellspacing="0" width="100%">
        <!-- LOGO -->
        <tr>
            <td bgcolor="#FFA73B" align="center">
                <table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
                    <tr>
                        <td align="center" valign="top" style="padding: 40px 10px 40px 10px;"> </td>
                    </tr>
                </table>
            </td>
        </tr>
        <tr>
            <td bgcolor="#FFA73B" align="center" style="padding: 0px 10px 0px 10px;">
                <table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
                    <tr>
                        <td bgcolor="#ffffff" align="center" valign="top" style="padding: 40px 20px 20px 20px; border-radius: 4px 4px 0px 0px; color: #111111; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 48px; font-weight: 400; letter-spacing: 4px; line-height: 48px;">
                            <h1 style="font-size: 48px; font-weight: 400; margin: 2;">Welcome @Model?.Name!</h1> <img src=" https://img.icons8.com/clouds/100/000000/handshake.png" width="125" height="120" style="display: block; border: 0px;" />
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
        <tr>
            <td bgcolor="#f4f4f4" align="center" style="padding: 0px 10px 0px 10px;">
                <table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
                    <tr>
                        <td bgcolor="#ffffff" align="left" style="padding: 20px 30px 40px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;">
                            <p style="margin: 0;">We're excited to have you get started at the MailKit Demo Platform. First, you need to confirm your account. Just press the button below.</p>
                        </td>
                    </tr>
                    <tr>
                        <td bgcolor="#ffffff" align="left">
                            <table width="100%" border="0" cellspacing="0" cellpadding="0">
                                <tr>
                                    <td bgcolor="#ffffff" align="center" style="padding: 20px 30px 60px 30px;">
                                        <table border="0" cellspacing="0" cellpadding="0">
                                            <tr>
                                                <td align="center" style="border-radius: 3px;" bgcolor="#FFA73B"><a href="#" target="_blank" style="font-size: 20px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; color: #ffffff; text-decoration: none; padding: 15px 25px; border-radius: 2px; border: 1px solid #FFA73B; display: inline-block;">Confirm Account</a></td>
                                            </tr>
                                        </table>
                                    </td>
                                </tr>
                            </table>
                        </td>
                    </tr> <!-- COPY -->
                    <tr>
                        <td bgcolor="#ffffff" align="left" style="padding: 0px 30px 0px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;">
                            <p style="margin: 0;">If that doesn't work, copy and paste the following link in your browser:</p>
                        </td>
                    </tr> <!-- COPY -->
                    <tr>
                        <td bgcolor="#ffffff" align="left" style="padding: 20px 30px 20px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;">
                            <p style="margin: 0;"><a href="#" target="_blank" style="color: #FFA73B;">Some URL to activate the account</a></p>
                        </td>
                    </tr>
                    <tr>
                        <td bgcolor="#ffffff" align="left" style="padding: 0px 30px 20px 30px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;">
                            <p style="margin: 0;">If you have any questions, just reply to this email—we're always happy to help out.</p>
                        </td>
                    </tr>
                    <tr>
                        <td bgcolor="#ffffff" align="left" style="padding: 0px 30px 40px 30px; border-radius: 0px 0px 4px 4px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;">
                            <p style="margin: 0;">Cheers,<br>BBB Team</p>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
        <tr>
            <td bgcolor="#f4f4f4" align="center" style="padding: 30px 10px 0px 10px;">
                <table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
                    <tr>
                        <td bgcolor="#FFECD1" align="center" style="padding: 30px 30px 30px 30px; border-radius: 4px 4px 4px 4px; color: #666666; font-family: 'Lato', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 400; line-height: 25px;">
                            <h2 style="font-size: 20px; font-weight: 400; color: #111111; margin: 0;">Need more help?</h2>
                            <p style="margin: 0;"><a href="#" target="_blank" style="color: #FFA73B;">We&rsquo;re here to help you out</a></p>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</body>

</html>

Create a new model for welcome emails to users

Inside our Models folder, we will create a new folder named WelcomeMail.cs and put two properties inside it. One for name and another for email. Remember to replace the namespace with your own project.

namespace MailKitDemo.Models.Emails
{
    public class WelcomeMail
    {
        public string? Name { get; set; }
        public string? Email { get; set; }
    }
}

Add Email Template Service to the Mail Service

In order to generate a new template for the mail we would like to send, we need a service to generate the string we later will format as HTML when sending the welcome mail to our user.

Open IMailService.cs and add the following at line 9:

using MailKitDemo.Models;

namespace MailKitDemo.Services
{
    public interface IMailService
    {
        Task<bool> SendAsync(MailData mailData, CancellationToken ct);
        Task<bool> SendWithAttachmentsAsync(MailDataWithAttachments mailData, CancellationToken ct);
        string GetEmailTemplate<T>(string emailTemplate, T emailTemplateModel);
    }
}

As you can see we are creating a generic method (A generic method is a method that is declared with type parameters). This is because we would like to reuse our code to generate multiple templates, without having to repeat ourselves. By doing it this way, we would only have to create a new model and template file, when adding a new type of mail to our project.

Open MailService and implement the updated interface, like below:

using MailKit.Net.Smtp;
using MailKit.Security;
using MailKitDemo.Configuration;
using MailKitDemo.Models;
using Microsoft.Extensions.Options;
using MimeKit;
using RazorEngineCore;
using System.Text;

namespace MailKitDemo.Services
{
    public class MailService : IMailService
    {
        private readonly MailSettings _settings;

        public MailService(IOptions<MailSettings> settings)
        {
            _settings = settings.Value;
        }

        public async Task<bool> SendWithAttachmentsAsync(MailDataWithAttachments mailData, CancellationToken ct = default)
        {
            try
            {
                // Initialize a new instance of the MimeKit.MimeMessage class
                var mail = new MimeMessage();

                #region Sender / Receiver
                // Sender
                mail.From.Add(new MailboxAddress(_settings.DisplayName, mailData.From ?? _settings.From));
                mail.Sender = new MailboxAddress(mailData.DisplayName ?? _settings.DisplayName, mailData.From ?? _settings.From);

                // Receiver
                foreach (string mailAddress in mailData.To)
                    mail.To.Add(MailboxAddress.Parse(mailAddress));

                // Set Reply to if specified in mail data
                if (!string.IsNullOrEmpty(mailData.ReplyTo))
                    mail.ReplyTo.Add(new MailboxAddress(mailData.ReplyToName, mailData.ReplyTo));

                // BCC
                // Check if a BCC was supplied in the request
                if (mailData.Bcc != null)
                {
                    // Get only addresses where value is not null or with whitespace. x = value of address
                    foreach (string mailAddress in mailData.Bcc.Where(x => !string.IsNullOrWhiteSpace(x)))
                        mail.Bcc.Add(MailboxAddress.Parse(mailAddress.Trim()));
                }

                // CC
                // Check if a CC address was supplied in the request
                if (mailData.Cc != null)
                {
                    foreach (string mailAddress in mailData.Cc.Where(x => !string.IsNullOrWhiteSpace(x)))
                        mail.Cc.Add(MailboxAddress.Parse(mailAddress.Trim()));
                }
                #endregion

                #region Content

                // Add Content to Mime Message
                var body = new BodyBuilder();
                mail.Subject = mailData.Subject;
                
                // Check if we got any attachments and add the to the builder for our message
                if (mailData.Attachments != null)
                {
                    byte[] attachmentFileByteArray;
                    foreach (IFormFile attachment in mailData.Attachments)
                    {
                        if (attachment.Length > 0)
                        {
                            using (MemoryStream memoryStream = new MemoryStream())
                            {
                                attachment.CopyTo(memoryStream);
                                attachmentFileByteArray = memoryStream.ToArray();
                            }
                            body.Attachments.Add(attachment.FileName, attachmentFileByteArray, ContentType.Parse(attachment.ContentType));
                        }
                    }
                }
                body.HtmlBody = mailData.Body;
                mail.Body = body.ToMessageBody();

                #endregion

                #region Send Mail

                using var smtp = new SmtpClient();

                if (_settings.UseSSL)
                {
                    await smtp.ConnectAsync(_settings.Host, _settings.Port, SecureSocketOptions.SslOnConnect, ct);
                }
                else if (_settings.UseStartTls)
                {
                    await smtp.ConnectAsync(_settings.Host, _settings.Port, SecureSocketOptions.StartTls, ct);
                }

                await smtp.AuthenticateAsync(_settings.UserName, _settings.Password, ct);
                await smtp.SendAsync(mail, ct);
                await smtp.DisconnectAsync(true, ct);

                return true;
                #endregion

            }
            catch (Exception)
            {
                return false;
            }
        }

        public async Task<bool> SendAsync(MailData mailData, CancellationToken ct = default) 
        {
            try
            {
                // Initialize a new instance of the MimeKit.MimeMessage class
                var mail = new MimeMessage();

                #region Sender / Receiver
                // Sender
                mail.From.Add(new MailboxAddress(_settings.DisplayName, mailData.From ?? _settings.From));
                mail.Sender = new MailboxAddress(mailData.DisplayName ?? _settings.DisplayName, mailData.From ?? _settings.From);

                // Receiver
                foreach (string mailAddress in mailData.To)
                    mail.To.Add(MailboxAddress.Parse(mailAddress));

                // Set Reply to if specified in mail data
                if(!string.IsNullOrEmpty(mailData.ReplyTo))
                    mail.ReplyTo.Add(new MailboxAddress(mailData.ReplyToName, mailData.ReplyTo));

                // BCC
                // Check if a BCC was supplied in the request
                if (mailData.Bcc != null)
                {
                    // Get only addresses where value is not null or with whitespace. x = value of address
                    foreach (string mailAddress in mailData.Bcc.Where(x => !string.IsNullOrWhiteSpace(x)))
                        mail.Bcc.Add(MailboxAddress.Parse(mailAddress.Trim()));
                }

                // CC
                // Check if a CC address was supplied in the request
                if (mailData.Cc != null)
                {
                    foreach (string mailAddress in mailData.Cc.Where(x => !string.IsNullOrWhiteSpace(x)))
                        mail.Cc.Add(MailboxAddress.Parse(mailAddress.Trim()));
                }
                #endregion

                #region Content

                // Add Content to Mime Message
                var body = new BodyBuilder();
                mail.Subject = mailData.Subject;
                body.HtmlBody = mailData.Body;
                mail.Body = body.ToMessageBody();

                #endregion

                #region Send Mail

                using var smtp = new SmtpClient();

                if (_settings.UseSSL)
                {
                    await smtp.ConnectAsync(_settings.Host, _settings.Port, SecureSocketOptions.SslOnConnect, ct);
                }
                else if (_settings.UseStartTls)
                {
                    await smtp.ConnectAsync(_settings.Host, _settings.Port, SecureSocketOptions.StartTls, ct);
                }

                await smtp.AuthenticateAsync(_settings.UserName, _settings.Password, ct);
                await smtp.SendAsync(mail, ct);
                await smtp.DisconnectAsync(true, ct);

                return true;
                #endregion

            }
            catch (Exception)
            {
                return false;
            }
        }

        public string GetEmailTemplate<T>(string emailTemplate, T emailTemplateModel)
        {
            string mailTemplate = LoadTemplate(emailTemplate);

            IRazorEngine razorEngine = new RazorEngine();
            IRazorEngineCompiledTemplate modifiedMailTemplate = razorEngine.Compile(mailTemplate);

            return modifiedMailTemplate.Run(emailTemplateModel);
        }

        public string LoadTemplate(string emailTemplate)
        {
            string baseDir = AppDomain.CurrentDomain.BaseDirectory;
            string templateDir = Path.Combine(baseDir, "Files/MailTemplates");
            string templatePath = Path.Combine(templateDir, $"{emailTemplate}.cshtml");

            using FileStream fileStream = new FileStream(templatePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            using StreamReader streamReader = new StreamReader(fileStream, Encoding.Default);

            string mailTemplate = streamReader.ReadToEnd();
            streamReader.Close();

            return mailTemplate;
        }
    }
}

So what happens here? Let’s take them step-by-step, starting from the bottom.

LoadTemplate() is responsible for returning the email template file, which we would like to modify with our model data. I generates a path for the template, then used a file- and stream reader to open the file, read it to the end and return it to the requesting method.

GetEmailTemplate() is responsible for modifying the mail template returned from LoadTemplate() with model data we parsed from the requesting method.

  1. We create a new RazorEngine object.
  2. We then compile the mail template file (in our case welcome.cshtml).
  3. Finally, we update the compiled file with data from our emailTemplateModel ( in our case WelcomeMail.cs) and return it.

Add a new endpoint to generate a Welcome Email to the user

Finally, we have to add a new endpoint in our MailController.cs file to accept a new POST request that is responsible for creating a new MailData object with data from our WelcomeMail object and lastly sending the mail.

Below is the final MailController with the final method to send an email using a template with ASP.NET Core.

using MailKitDemo.Models;
using MailKitDemo.Models.Emails;
using MailKitDemo.Services;
using Microsoft.AspNetCore.Mvc;

namespace MailKitDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class MailController : ControllerBase
    {
        private readonly IMailService _mail;

        public MailController(IMailService mail)
        {
            _mail = mail;
        }

        [HttpPost("sendmail")]
        public async Task<IActionResult> SendMailAsync(MailData mailData)
        {
            bool result = await _mail.SendAsync(mailData, new CancellationToken());

            if (result)
            {
                return StatusCode(StatusCodes.Status200OK, "Mail has successfully been sent.");
            } 
            else
            {
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occured. The Mail could not be sent.");
            }
        }

        [HttpPost("sendemailwithattachment")]
        public async Task<IActionResult> SendMailWithAttachmentAsync([FromForm]MailDataWithAttachments mailData)
        {
            bool result = await _mail.SendWithAttachmentsAsync(mailData, new CancellationToken());

            if (result)
            {
                return StatusCode(StatusCodes.Status200OK, "Mail with attachment has successfully been sent.");
            }
            else
            {
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occured. The Mail with attachment could not be sent.");
            }
        }

        [HttpPost("sendemailusingtemplate")]
        public async Task<IActionResult> SendEmailUsingTemplate(WelcomeMail welcomeMail)
        {
            // Create MailData object
            MailData mailData = new MailData(
                new List<string> { welcomeMail.Email }, 
                "Welcome to the MailKit Demo", 
                _mail.GetEmailTemplate("welcome", welcomeMail));


            bool sendResult = await _mail.SendAsync(mailData, new CancellationToken());

            if (sendResult)
            {
                return StatusCode(StatusCodes.Status200OK, "Mail has successfully been sent using template.");
            }
            else
            {
                return StatusCode(StatusCodes.Status500InternalServerError, "An error occured. The Mail could not be sent.");
            }
        }
    }
}

On lines 53 – 56 we create the MailData object with the receiver, and subject and also request a generation of the mail template named welcome along with the WelcomeMail object.

On line 59 we request the mail service to send the email async with the MailData object now containing our modified HTML template.

Finally, we return a status to the client requesting this endpoint with a success or non-success message along with an appropriate status code.

Testing the email service for sending mails using HTML templates

Now for the final part of this article. Testing of our new endpoint responsible for sending emails using a template in ASP.NET Core.

Spin up (F5) the application and make a POST request in the swagger interface, like I have done below:

send mail using a template in asp.net core
Send POST request for sending email using template to user

Let’s check it out in our email client.

Welcome Email sent from ASP.NET Core using MailKit

Wohaa! The mail has been dispatched from our application and formatted as HTML when sent to the receiver. It looks great and the Razor Engine has updated our placeholders with data from the model. Perfect!

Summary

In this article, you learned how to send emails with ASP.NET Core. You now got the knowledge to implement MailKit, an SMTP service, and a generic mail template service in your applications. I have added a Github link below, if you would like to see the source code, download it, etc…

Emails are still a crucial communication method and are widely used in big applications at Google, Facebook, Github, Twitter, Banking, Authentication Providers, etc… You are now able to add that feature to your applications and use it the same way they do. (Please avoid spamming your users 😉 ).

I hope you like my article. Please let me know your thoughts in the comments below. If you got any issues, suggestions, or questions, please also leave them below. I will get back to you ASAP. Happy coding out there! 😀

Source Code Download – https://github.com/Christian-Schou/MailKit-Demo-ASP.Net-Core.

Tags: .NET 6.Net CoreAPIASP.NET CoreC#DevelopmentEmailMailMailKitSMTPWeb
Previous Post

How to use Azure Blob Storage in an ASP.NET Core Web API to list, upload, download, and delete files

Next Post

How to use XML with C# – A beginners guide for basic XML operations in .NET

ईसाई

ईसाई

Hello 👋 My name is Christian and I am 26 years old. I'm an educated Software Developer with a primary focus on C#, .NET Core, Python, and PowerShell. Currently, I'm expanding my skills in Software Robots and Cloud Architecture. In some of my spare time, I share my knowledge about tech stuff on my blog.

Related Posts

watchdog
ASP.NET Core

The #1 guide to show real-time .NET 6 logs for Web Apps and APIs in a modern way using WatchDog for Free

by ईसाई
2022-4-अगस्त
0

A reader recently asked me for a more modern way to view log files for requests and exceptions in a...

Read more
restful web api

How to build a RESTful Web API using ASP.NET Core and Entity Framework Core (.NET 6)

2022-25-जुलाई
dynamically register entities

How to Dynamically Register Entities in DbContext by Extending ModelBuilder?

2022-23-जुलाई
Dockerize ASP.NET Core

How to Compose an ASP.NET Core Web API (.NET 6) with an MS SQL Server 2022 on Linux in Docker

2022-19-जुलाई
pattern matching in switch

How to do pattern matching in switch statements – C# version >= 7.0

2022-11-जुलाई
Next Post
How to use XML with C# – A beginners guide for basic XML operations in .NET

How to use XML with C# - A beginners guide for basic XML operations in .NET

प्रातिक्रिया दे जवाब रद्द करें

आपका ईमेल पता प्रकाशित नहीं किया जाएगा. आवश्यक फ़ील्ड चिह्नित हैं *

क्रिश्चियन शॉ

क्रिश्चियन शॉ

Software Developer

Hello - my name is Christian and I am 26 years old. I'm an educated Software Developer with a primary focus on C#, .NET Core, Python, and PowerShell. Currently, I'm expanding my skills in Software Robots and Cloud Architecture. In some of my spare time, I share my knowledge about tech stuff on my blog.

Recent articles

personal website
Career

Top 6 things to add on your personal website to get hired for a tech job

by ईसाई
2022-7-अगस्त
0

Back in the days before the internet was a thing like it is today, we used to have business cards...

Read more
watchdog

The #1 guide to show real-time .NET 6 logs for Web Apps and APIs in a modern way using WatchDog for Free

2022-4-अगस्त
get hired for a tech job

5 tips to help you get hired for a tech job

2022-31-जुलाई
restful web api

How to build a RESTful Web API using ASP.NET Core and Entity Framework Core (.NET 6)

2022-25-जुलाई
dynamically register entities

How to Dynamically Register Entities in DbContext by Extending ModelBuilder?

2022-23-जुलाई

क्रिश्चियन शॉ

Software Developer

Hello - my name is Christian and I am 26 years old. I'm an educated Software Developer with a primary focus on C#, .NET Core, Python, and PowerShell. Currently, I'm expanding my skills in Software Robots and Cloud Architecture. In some of my spare time, I share my knowledge about tech stuff on my blog.

Recent articles

personal website

Top 6 things to add on your personal website to get hired for a tech job

2022-7-अगस्त
watchdog

The #1 guide to show real-time .NET 6 logs for Web Apps and APIs in a modern way using WatchDog for Free

2022-4-अगस्त
get hired for a tech job

5 tips to help you get hired for a tech job

2022-31-जुलाई
  • hi_INहिन्दी
    • da_DKDansk
    • en_USEnglish
    • de_DEDeutsch
    • pt_BRPortuguês do Brasil
  • Contact
  • गोपनीयता नीति
  • सेवा की शर्तें

© 2022 क्रिश्चियन शॉ - All rights reserved.

No Result
View All Result
  • होम
  • Blog
    • प्रोग्रामिंग
      • C#
      • पॉवरशेल
      • Python
      • SQL
    • वर्डप्रेस
      • ट्युटोरियल
    • क्लाउड
    • होम ऑटोमेशन
      • होम असिस्टेंट
    • Career
  • सेवाएं
  • शब्दकोष
  • About

© 2022 क्रिश्चियन शॉ - All rights reserved.

मैं आपकी वरीयताओं को याद करके और बार-बार आने वाली यात्राओं को याद करके आपको सबसे अधिक प्रासंगिक अनुभव देने के लिए अपनी वेबसाइट पर कुकीज़ का उपयोग करता हूं। “स्वीकार करें” पर क्लिक करके, आप सभी कुकीज़ के उपयोग के लिए सहमति देते हैं।
मेरी निजी जानकारी न बेचें.
कुकी सेटिंगACCEPT
गोपनीयता और कुकीज़ नीति

गोपनीयता अवलोकन

This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
CookieDurationDescription
__gads1 year 24 daysThe __gads cookie, set by Google, is stored under DoubleClick domain and tracks the number of times users see an advert, measures the success of the campaign and calculates its revenue. This cookie can only be read from the domain they are set on and will not track any data while browsing through other sites.
_ga2 yearsThe _ga cookie, installed by Google Analytics, calculates visitor, session and campaign data and also keeps track of site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognize unique visitors.
_ga_0J2F6JVWSD2 yearsThis cookie is installed by Google Analytics.
_gat_gtag_UA_84232734_11 minuteSet by Google to distinguish users.
_gid1 dayInstalled by Google Analytics, _gid cookie stores information on how visitors use a website, while also creating an analytics report of the website's performance. Some of the data that are collected include the number of visitors, their source, and the pages they visit anonymously.
YouTube2 yearsYouTube sets this cookie via embedded youtube-videos and registers anonymous statistical data. I embed YouTube videos in my articles/tutorials - you won't get the full experience of the articles if this is deactivated.
Advertisement
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
CookieDurationDescription
IDE1 year 24 daysGoogle DoubleClick IDE cookies are used to store information about how the user uses the website to present them with relevant ads and according to the user profile.
test_cookie15 minutesThe test_cookie is set by doubleclick.net and is used to determine if the user's browser supports cookies.
VISITOR_INFO1_LIVE5 months 27 daysA cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface.
YSCsessionYSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages.
yt-remote-connected-devicesneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
yt-remote-device-idneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
Others
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.
SAVE & ACCEPT
Powered by CookieYes Logo