Sử dụng MailDev để kiểm thử gửi email trong phát triển ứng dụng

0 0 0

Người đăng: Đặng Việt Anh

Theo Viblo Asia

Trong quá trình phát triển ứng dụng, việc kiểm tra chức năng gửi email thường gặp nhiều thách thức. Từ việc cẩn thận để không gửi email thử nghiệm đến người dùng thật, đến khó khăn trong việc kiểm tra nội dung và định dạng email. Bài viết này giới thiệu MailDev - một công cụ mạnh mẽ giúp đơn giản hóa quy trình debug email trong môi trường phát triển ASP.NET Core.

MailDev là gì?

MailDev là một SMTP server giả lập và giao diện web cho phép xem các email được gửi từ ứng dụng của bạn trong quá trình phát triển. Nó chạy cục bộ, không gửi email ra ngoài và cung cấp giao diện thân thiện để kiểm tra nội dung email.

image.png

Lợi ích của MailDev

  • An toàn cho môi trường phát triển: Không gửi email thử nghiệm đến người dùng thật
  • Kiểm tra trực quan: Dễ dàng xem nội dung HTML, CSS và attachment
  • Không giới hạn số lượng email: Không bị giới hạn bởi các nhà cung cấp email như Gmail
  • Đơn giản và nhẹ: Dễ dàng triển khai với Docker
  • Tiết kiệm thời gian: Không cần tạo tài khoản email thật để kiểm tra

Cài đặt MailDev với Docker

MailDev có thể được cài đặt dễ dàng sử dụng Docker với một lệnh duy nhất:

docker run -d --name maildev -p 1080:1080 -p 1025:1025 maildev/maildev
  • Port 1025: SMTP server nhận email từ ứng dụng
  • Port 1080: Web UI để xem các email đã nhận

Tích hợp MailDev vào dự án ASP.NET Core

1. Cấu hình appsettings.json

Thêm cấu hình email cho môi trường phát triển trong file appsettings.Development.json:

{ "EmailSettings": { "SmtpServer": "localhost", "Port": 1025, "SenderName": "YourApp", "SenderEmail": "no-reply@yourapp.com", "Username": "", "Password": "" }
}

2. Tạo class cấu hình Email

public class EmailSettings
{ public string SmtpServer { get; set; } public int Port { get; set; } public string SenderName { get; set; } public string SenderEmail { get; set; } public string Username { get; set; } public string Password { get; set; }
}

3. Tạo interface cho Email Service

public interface IEmailService
{ Task SendEmailAsync(string to, string subject, string htmlContent);
}

4. Triển khai Email Service sử dụng MailKit

Đầu tiên, cài đặt package MailKit:

dotnet add package MailKit

Sau đó, tạo service để gửi email:

using MailKit.Net.Smtp;
using Microsoft.Extensions.Options;
using MimeKit;
using System;
using System.Threading.Tasks; public class EmailService : IEmailService
{ private readonly EmailSettings _emailSettings; private readonly ILogger<EmailService> _logger; public EmailService(IOptions<EmailSettings> emailSettings, ILogger<EmailService> logger) { _emailSettings = emailSettings.Value; _logger = logger; } public async Task SendEmailAsync(string to, string subject, string htmlContent) { try { var email = new MimeMessage(); email.From.Add(new MailboxAddress(_emailSettings.SenderName, _emailSettings.SenderEmail)); email.To.Add(MailboxAddress.Parse(to)); email.Subject = subject; var builder = new BodyBuilder { HtmlBody = htmlContent }; email.Body = builder.ToMessageBody(); using (var smtp = new SmtpClient()) { // MailDev không yêu cầu SSL await smtp.ConnectAsync(_emailSettings.SmtpServer, _emailSettings.Port, false); // MailDev không yêu cầu xác thực // Bỏ qua bước AuthenticateAsync await smtp.SendAsync(email); await smtp.DisconnectAsync(true); _logger.LogInformation($"Email sent to MailDev. View at http://localhost:1080"); } } catch (Exception ex) { _logger.LogError($"Error sending email: {ex.Message}"); throw; } }
}

5. Đăng ký service trong Startup.cs hoặc Program.cs

// Program.cs (.NET 6+)
builder.Services.Configure<EmailSettings>( builder.Configuration.GetSection("EmailSettings"));
builder.Services.AddScoped<IEmailService, EmailService>(); // hoặc Startup.cs (.NET 5 hoặc trước đó)
services.Configure<EmailSettings>( Configuration.GetSection("EmailSettings"));
services.AddScoped<IEmailService, EmailService>();

Sử dụng Email Service trong Controller

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{ private readonly IEmailService _emailService; public UserController(IEmailService emailService) { _emailService = emailService; } [HttpPost("register")] public async Task<IActionResult> Register(RegisterModel model) { // Xử lý đăng ký người dùng // Gửi email xác thực string verificationLink = $"https://yourapp.com/verify?token={generatedToken}"; string emailContent = $@" <h1>Xác thực tài khoản</h1> <p>Chào {model.FullName},</p> <p>Vui lòng click vào link bên dưới để xác thực tài khoản:</p> <p><a href='{verificationLink}'>Xác thực ngay</a></p> <p>Link xác thực có hiệu lực trong 24 giờ.</p> <p>Trân trọng,<br>Đội ngũ phát triển</p> "; await _emailService.SendEmailAsync( model.Email, "Xác thực tài khoản", emailContent); return Ok(new { message = "Đăng ký thành công. Vui lòng kiểm tra email để xác thực tài khoản." }); }
}

Tạo Email Template Sử dụng Razor

Để email chuyên nghiệp hơn, bạn có thể sử dụng Razor Template cho email:

  1. Cài đặt package Razor Engine:
dotnet add package RazorLight
  1. Tạo Email Template trong thư mục Templates:
<!-- Templates/VerificationEmail.cshtml -->
@model VerificationEmailModel <!DOCTYPE html>
<html>
<head> <meta charset="utf-8" /> <style> body { font-family: Arial, sans-serif; line-height: 1.6; } .container { max-width: 600px; margin: 0 auto; padding: 20px; } .button { display: inline-block; background-color: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px; } </style>
</head>
<body> <div class="container"> <h1>Xác thực tài khoản</h1> <p>Chào @Model.Name,</p> <p>Vui lòng click vào button bên dưới để xác thực tài khoản:</p> <p><a href="@Model.VerificationLink" class="button">Xác thực ngay</a></p> <p>Hoặc copy link sau vào trình duyệt: @Model.VerificationLink</p> <p>Link xác thực có hiệu lực trong 24 giờ.</p> <p>Trân trọng,<br>Đội ngũ phát triển</p> </div>
</body>
</html>
  1. Tạo class model cho template:
public class VerificationEmailModel
{ public string Name { get; set; } public string VerificationLink { get; set; }
} public class RegisterModel
{ public string FullName { get; set; } public string Email { get; set; }
}
  1. Triển khai giải pháp render template:
using RazorLight;
using System.IO;
using System.Threading.Tasks; public class EmailTemplateService
{ private readonly RazorLightEngine _engine; public EmailTemplateService() { _engine = new RazorLightEngineBuilder() .UseFileSystemProject(Path.Combine(Directory.GetCurrentDirectory(), "Templates")) .UseMemoryCachingProvider() .Build(); } public async Task<string> RenderTemplateAsync<T>(string templateName, T model) { return await _engine.CompileRenderAsync(templateName, model); }
}
  1. Sử dụng template trong Email Service:
// Trong UserController
private readonly IEmailService _emailService;
private readonly EmailTemplateService _templateService; public UserController(IEmailService emailService, EmailTemplateService templateService)
{ _emailService = emailService; _templateService = templateService;
} [HttpPost("register")]
public async Task<IActionResult> Register(RegisterModel model)
{ // Xử lý đăng ký // Render email template var emailModel = new VerificationEmailModel { Name = model.FullName, VerificationLink = $"https://yourapp.com/verify?token={generatedToken}" }; string emailContent = await _templateService.RenderTemplateAsync( "VerificationEmail.cshtml", emailModel); // Gửi email await _emailService.SendEmailAsync(model.Email, "Xác thực tài khoản", emailContent); return Ok(new { message = "Đăng ký thành công" });
}

Debug Email với MailDev

Sau khi triển khai xong, quy trình debug email sẽ như sau:

  1. Chạy ứng dụng ASP.NET Core trong chế độ Development
  2. Kích hoạt hành động gửi email (đăng ký, quên mật khẩu, v.v.)
  3. Mở trình duyệt và truy cập http://localhost:1080
  4. Tất cả email gửi từ ứng dụng sẽ xuất hiện trong giao diện web MailDev
  5. Bạn có thể xem HTML render, raw HTML, source và thậm chí attachment

MailDev Interface

Chuyển sang Production

Khi triển khai lên môi trường production, bạn chỉ cần thay đổi cấu hình SMTP trong appsettings.Production.json để sử dụng SMTP server thật:

{ "EmailSettings": { "SmtpServer": "smtp.gmail.com", "Port": 587, "SenderName": "YourApp", "SenderEmail": "your-app@gmail.com", "Username": "your-app@gmail.com", "Password": "your-app-password" }
}

Và cập nhật EmailService để sử dụng SSL và xác thực khi không ở môi trường Development:

public async Task SendEmailAsync(string to, string subject, string htmlContent)
{ try { var email = new MimeMessage(); // ... code như trước using (var smtp = new SmtpClient()) { var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); bool isDevelopment = environment == "Development"; await smtp.ConnectAsync( _emailSettings.SmtpServer, _emailSettings.Port, !isDevelopment); // Sử dụng SSL trên production // Xác thực chỉ khi không phải môi trường Development if (!isDevelopment && !string.IsNullOrEmpty(_emailSettings.Username)) { await smtp.AuthenticateAsync(_emailSettings.Username, _emailSettings.Password); } await smtp.SendAsync(email); await smtp.DisconnectAsync(true); } } catch (Exception ex) { _logger.LogError($"Error sending email: {ex.Message}"); throw; }
}

Kết luận

MailDev là một công cụ rất hữu ích trong quá trình phát triển ASP.NET Core, giúp đơn giản hóa việc debug email. Với cách triển khai như hướng dẫn trên, bạn có thể:

  1. Kiểm tra chính xác nội dung email mà không cần gửi đến người dùng thật
  2. Phát hiện và sửa lỗi định dạng, nội dung email nhanh chóng
  3. Tiết kiệm thời gian trong quy trình phát triển
  4. Chuyển đổi dễ dàng giữa môi trường development và production

Bình luận

Bài viết tương tự

- vừa được xem lúc

Các loại tham chiếu Nullable trong C# (Phần 1)

1. Giới thiệu. C# 8.0 giới thiệu kiểu tham chiếu nullable và kiểu tham chiếu non-nullable cho phép bạn đưa ra các lựa chọn quan trọng về thuộc tính cho các biến kiểu tham chiếu:.

0 0 57

- vừa được xem lúc

Command pattern qua ví dụ !

Command pattern là gì . Command pattern khá phổ biến trong C #, đặc biệt khi chúng ta muốn trì hoãn hoặc xếp hàng đợi việc thực hiện một yêu cầu hoặc khi chúng ta muốn theo dõi các hoạt động. Hơn nữa, chúng ta có thể hoàn tác tác chúng. .

0 0 198

- vừa được xem lúc

Hiểu Liskov Substitution Principle qua ví dụ !

Liskov Substitution Principle là gì . Nguyên tắc đóng mở xác đinh rằng các instance của lớp con có thể thay thế được instance lớp cha mà vẫn đảm bảo tính đúng đắn của chương trình.

0 0 40

- vừa được xem lúc

Creating custom Controls Wpf

Introduction. Wpf/winforms provides various controls like Buttons, Textbox, TextBlock, Labels etc.

0 0 58

- vừa được xem lúc

[P1] Chọn công nghệ nào để xây dựng website?

Hiện nay nhu cầu phát triển website, app tăng rất cao do xu hướng "số hóa 4.0" trong và ngoài nước.

0 0 88

- vừa được xem lúc

Kiểu dữ liệu trong C#

Dẫn nhập. Ở bài BIẾN TRONG C# chúng ta đã tìm hiểu về biến và có một thành phần không thể thiếu khi khai báo biến – Đó là kiểu dữ liệu.

0 0 41