├── .gitignore ├── EmailApp ├── EmailApp.sln ├── EmailApp │ ├── Controllers │ │ └── WeatherForecastController.cs │ ├── EmailApp.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── WeatherForecast.cs │ ├── appsettings.Development.json │ └── appsettings.json └── EmailService │ ├── EmailConfiguration.cs │ ├── EmailSender.cs │ ├── EmailService.csproj │ ├── IEmailSender.cs │ └── Message.cs ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /EmailApp/EmailApp/obj 2 | /EmailApp/EmailApp/bin 3 | /EmailApp/EmailService/obj 4 | /EmailApp/EmailService/bin 5 | -------------------------------------------------------------------------------- /EmailApp/EmailApp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29503.13 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EmailApp", "EmailApp\EmailApp.csproj", "{48A990F4-AF11-4F6E-BFAB-3FC8230E496A}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EmailService", "EmailService\EmailService.csproj", "{3D086448-9DC7-4979-9907-58BC1C0DC8C7}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {48A990F4-AF11-4F6E-BFAB-3FC8230E496A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {48A990F4-AF11-4F6E-BFAB-3FC8230E496A}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {48A990F4-AF11-4F6E-BFAB-3FC8230E496A}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {48A990F4-AF11-4F6E-BFAB-3FC8230E496A}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {3D086448-9DC7-4979-9907-58BC1C0DC8C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {3D086448-9DC7-4979-9907-58BC1C0DC8C7}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {3D086448-9DC7-4979-9907-58BC1C0DC8C7}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {3D086448-9DC7-4979-9907-58BC1C0DC8C7}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {2AA5008D-F1F2-473F-B637-CE0221F1F1E2} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /EmailApp/EmailApp/Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using EmailService; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace MailApp.Controllers 11 | { 12 | [ApiController] 13 | [Route("[controller]")] 14 | public class WeatherForecastController : ControllerBase 15 | { 16 | private static readonly string[] Summaries = new[] 17 | { 18 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 19 | }; 20 | 21 | private readonly IEmailSender _emailSender; 22 | 23 | public WeatherForecastController(IEmailSender emailSender) 24 | { 25 | _emailSender = emailSender; 26 | } 27 | 28 | [HttpGet] 29 | public async Task> Get() 30 | { 31 | var rng = new Random(); 32 | 33 | var message = new Message(new string[] { "codemazetest@mailinator.com" }, "Test email async", "This is the content from our async email.", null); 34 | await _emailSender.SendEmailAsync(message); 35 | 36 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 37 | { 38 | Date = DateTime.Now.AddDays(index), 39 | TemperatureC = rng.Next(-20, 55), 40 | Summary = Summaries[rng.Next(Summaries.Length)] 41 | }) 42 | .ToArray(); 43 | } 44 | 45 | [HttpPost] 46 | public async Task> Post() 47 | { 48 | var rng = new Random(); 49 | 50 | var files = Request.Form.Files.Any() ? Request.Form.Files : new FormFileCollection(); 51 | 52 | var message = new Message(new string[] { "codemazetest@mailinator.com" }, "Test mail with Attachments", "This is the content from our mail with attachments.", files); 53 | await _emailSender.SendEmailAsync(message); 54 | 55 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 56 | { 57 | Date = DateTime.Now.AddDays(index), 58 | TemperatureC = rng.Next(-20, 55), 59 | Summary = Summaries[rng.Next(Summaries.Length)] 60 | }) 61 | .ToArray(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /EmailApp/EmailApp/EmailApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /EmailApp/EmailApp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace MailApp 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /EmailApp/EmailApp/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:52088/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "MailApp": { 12 | "commandName": "Project", 13 | "launchBrowser": false, 14 | "launchUrl": "weatherforecast", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | }, 18 | "applicationUrl": "https://localhost:5001/" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /EmailApp/EmailApp/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using EmailService; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.AspNetCore.Http.Features; 9 | using Microsoft.AspNetCore.HttpsPolicy; 10 | using Microsoft.AspNetCore.Mvc; 11 | using Microsoft.Extensions.Configuration; 12 | using Microsoft.Extensions.DependencyInjection; 13 | using Microsoft.Extensions.Hosting; 14 | using Microsoft.Extensions.Logging; 15 | 16 | namespace MailApp 17 | { 18 | public class Startup 19 | { 20 | public Startup(IConfiguration configuration) 21 | { 22 | Configuration = configuration; 23 | } 24 | 25 | public IConfiguration Configuration { get; } 26 | 27 | // This method gets called by the runtime. Use this method to add services to the container. 28 | public void ConfigureServices(IServiceCollection services) 29 | { 30 | var emailConfig = Configuration 31 | .GetSection("EmailConfiguration") 32 | .Get(); 33 | services.AddSingleton(emailConfig); 34 | services.AddScoped(); 35 | 36 | services.Configure(o => { 37 | o.ValueLengthLimit = int.MaxValue; 38 | o.MultipartBodyLengthLimit = int.MaxValue; 39 | o.MemoryBufferThreshold = int.MaxValue; 40 | }); 41 | 42 | services.AddControllers(); 43 | } 44 | 45 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 46 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 47 | { 48 | if (env.IsDevelopment()) 49 | { 50 | app.UseDeveloperExceptionPage(); 51 | } 52 | 53 | app.UseHttpsRedirection(); 54 | 55 | app.UseRouting(); 56 | 57 | app.UseAuthorization(); 58 | 59 | app.UseEndpoints(endpoints => 60 | { 61 | endpoints.MapControllers(); 62 | }); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /EmailApp/EmailApp/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MailApp 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EmailApp/EmailApp/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /EmailApp/EmailApp/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "EmailConfiguration": { 10 | "From": "codemazetest@gmail.com", 11 | "SmtpServer": "smtp.gmail.com", 12 | "Port": 465, 13 | "Username": "codemazetest@gmail.com", 14 | "Password": "password for your email" 15 | }, 16 | "AllowedHosts": "*" 17 | } 18 | -------------------------------------------------------------------------------- /EmailApp/EmailService/EmailConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EmailService 6 | { 7 | public class EmailConfiguration 8 | { 9 | public string From { get; set; } 10 | public string SmtpServer { get; set; } 11 | public int Port { get; set; } 12 | public string UserName { get; set; } 13 | public string Password { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EmailApp/EmailService/EmailSender.cs: -------------------------------------------------------------------------------- 1 | using MailKit.Net.Smtp; 2 | using MimeKit; 3 | using System; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace EmailService 9 | { 10 | public class EmailSender : IEmailSender 11 | { 12 | private readonly EmailConfiguration _emailConfig; 13 | 14 | public EmailSender(EmailConfiguration emailConfig) 15 | { 16 | _emailConfig = emailConfig; 17 | } 18 | 19 | public void SendEmail(Message message) 20 | { 21 | var emailMessage = CreateEmailMessage(message); 22 | 23 | Send(emailMessage); 24 | } 25 | 26 | public async Task SendEmailAsync(Message message) 27 | { 28 | var mailMessage = CreateEmailMessage(message); 29 | 30 | await SendAsync(mailMessage); 31 | } 32 | 33 | private MimeMessage CreateEmailMessage(Message message) 34 | { 35 | var emailMessage = new MimeMessage(); 36 | emailMessage.From.Add(new MailboxAddress(_emailConfig.From)); 37 | emailMessage.To.AddRange(message.To); 38 | emailMessage.Subject = message.Subject; 39 | 40 | var bodyBuilder = new BodyBuilder { HtmlBody = string.Format("

{0}

", message.Content) }; 41 | 42 | if (message.Attachments != null && message.Attachments.Any()) 43 | { 44 | byte[] fileBytes; 45 | foreach (var attachment in message.Attachments) 46 | { 47 | using (var ms = new MemoryStream()) 48 | { 49 | attachment.CopyTo(ms); 50 | fileBytes = ms.ToArray(); 51 | } 52 | 53 | bodyBuilder.Attachments.Add(attachment.FileName, fileBytes, ContentType.Parse(attachment.ContentType)); 54 | } 55 | } 56 | 57 | emailMessage.Body = bodyBuilder.ToMessageBody(); 58 | return emailMessage; 59 | } 60 | 61 | private void Send(MimeMessage mailMessage) 62 | { 63 | using (var client = new SmtpClient()) 64 | { 65 | try 66 | { 67 | client.Connect(_emailConfig.SmtpServer, _emailConfig.Port, true); 68 | client.AuthenticationMechanisms.Remove("XOAUTH2"); 69 | client.Authenticate(_emailConfig.UserName, _emailConfig.Password); 70 | 71 | client.Send(mailMessage); 72 | } 73 | catch 74 | { 75 | //log an error message or throw an exception, or both. 76 | throw; 77 | } 78 | finally 79 | { 80 | client.Disconnect(true); 81 | client.Dispose(); 82 | } 83 | } 84 | } 85 | 86 | private async Task SendAsync(MimeMessage mailMessage) 87 | { 88 | using (var client = new SmtpClient()) 89 | { 90 | try 91 | { 92 | await client.ConnectAsync(_emailConfig.SmtpServer, _emailConfig.Port, true); 93 | client.AuthenticationMechanisms.Remove("XOAUTH2"); 94 | await client.AuthenticateAsync(_emailConfig.UserName, _emailConfig.Password); 95 | 96 | await client.SendAsync(mailMessage); 97 | } 98 | catch 99 | { 100 | //log an error message or throw an exception, or both. 101 | throw; 102 | } 103 | finally 104 | { 105 | await client.DisconnectAsync(true); 106 | client.Dispose(); 107 | } 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /EmailApp/EmailService/EmailService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /EmailApp/EmailService/IEmailSender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace EmailService 7 | { 8 | public interface IEmailSender 9 | { 10 | void SendEmail(Message message); 11 | Task SendEmailAsync(Message message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /EmailApp/EmailService/Message.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using MimeKit; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace EmailService 9 | { 10 | public class Message 11 | { 12 | public List To { get; set; } 13 | public string Subject { get; set; } 14 | public string Content { get; set; } 15 | 16 | public IFormFileCollection Attachments { get; set; } 17 | 18 | public Message(IEnumerable to, string subject, string content, IFormFileCollection attachments) 19 | { 20 | To = new List(); 21 | 22 | To.AddRange(to.Select(x => new MailboxAddress(x))); 23 | Subject = subject; 24 | Content = content; 25 | Attachments = attachments; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Code Maze 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to Send Email with Attachments in ASP.NET Core 2 | ## https://code-maze.com/send-email-with-attachments-aspnetcore-2/ 3 | This repo contains the source code for "How to Send Email with Attachments in ASP.NET Core" article on Code Maze 4 | --------------------------------------------------------------------------------