Skip to main content

Overview

MvcCore Utilidades provides email sending functionality through the MailsController, which uses .NET’s built-in SmtpClient and configuration from appsettings.json to send emails via SMTP.

Key Components

MailsController

Controller that handles email sending operations. Namespace: MvcCoreUtilidades.Controllers Dependencies:
  • IConfiguration - Injected via constructor to read mail settings

Configuration

1

Configure appsettings.json

Add email configuration to your appsettings.json file:
{
  "MailSettings": {
    "Credentials": {
      "User": "[email protected]",
      "Password": "your-app-password"
    }
  },
  "Server": {
    "Host": "smtp.gmail.com",
    "Port": 587,
    "Ssl": true,
    "DefaultCredentials": false
  }
}
Store sensitive credentials using User Secrets or environment variables in production, not directly in appsettings.json.
2

Register dependencies

The controller uses IConfiguration which is automatically registered in ASP.NET Core:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();
// IConfiguration is already available

Configuration Structure

MailSettings Section

MailSettings.Credentials.User
string
required
The email address to send from (SMTP username)
MailSettings.Credentials.Password
string
required
The password or app-specific password for the email account

Server Section

Server.Host
string
required
SMTP server hostname (e.g., smtp.gmail.com, smtp.office365.com)
Server.Port
int
required
SMTP server port (typically 587 for TLS, 465 for SSL, 25 for unencrypted)
Server.Ssl
bool
required
Enable SSL/TLS encryption (recommended: true)
Server.DefaultCredentials
bool
required
Use Windows credentials (typically false for SMTP authentication)

Controller Implementation

SendMail (GET)

Displays the email composition form.
public IActionResult SendMail()
{
    return View();
}

SendMail (POST)

Sends an email asynchronously.
to
string
required
Recipient email address
asunto
string
required
Email subject line
mensaje
string
required
Email body content (supports HTML)
[HttpPost]
public async Task<IActionResult> SendMail(string to, string asunto, string mensaje)
{
    // Read configuration
    string user = this.configuration.GetValue<string>("MailSettings:Credentials:User");
    
    // Create mail message
    MailMessage mail = new MailMessage();
    mail.From = new MailAddress(user);
    mail.To.Add(to);
    mail.Subject = asunto;
    mail.Body = mensaje;
    mail.IsBodyHtml = true;
    mail.Priority = MailPriority.Normal;
    
    // Read SMTP settings
    string password = this.configuration.GetValue<string>("MailSettings:Credentials:Password");
    string host = this.configuration.GetValue<string>("Server:Host");
    int port = this.configuration.GetValue<int>("Server:Port");
    bool ssl = this.configuration.GetValue<bool>("Server:Ssl");
    bool defaultCredentials = this.configuration.GetValue<bool>("Server:DefaultCredentials");
    
    // Configure SMTP client
    SmtpClient client = new SmtpClient();
    client.Host = host;
    client.Port = port;
    client.EnableSsl = ssl;
    client.UseDefaultCredentials = defaultCredentials;  // Set BEFORE credentials
    
    NetworkCredential credentials = new NetworkCredential(user, password);
    client.Credentials = credentials;  // Set AFTER UseDefaultCredentials
    
    // Send email
    await client.SendMailAsync(mail);
    
    ViewData["MENSAJE"] = "Mensaje enviado correctamente.";
    return View();
}
Important: Set UseDefaultCredentials = false BEFORE setting Credentials. The order matters!

Common SMTP Configurations

Gmail

{
  "MailSettings": {
    "Credentials": {
      "User": "[email protected]",
      "Password": "your-16-digit-app-password"
    }
  },
  "Server": {
    "Host": "smtp.gmail.com",
    "Port": 587,
    "Ssl": true,
    "DefaultCredentials": false
  }
}
Gmail requires an App Password when 2FA is enabled. Regular passwords won’t work.

Microsoft 365 / Outlook

{
  "MailSettings": {
    "Credentials": {
      "User": "[email protected]",
      "Password": "your-password"
    }
  },
  "Server": {
    "Host": "smtp.office365.com",
    "Port": 587,
    "Ssl": true,
    "DefaultCredentials": false
  }
}

SendGrid

{
  "MailSettings": {
    "Credentials": {
      "User": "apikey",
      "Password": "SG.your-sendgrid-api-key"
    }
  },
  "Server": {
    "Host": "smtp.sendgrid.net",
    "Port": 587,
    "Ssl": true,
    "DefaultCredentials": false
  }
}

Complete Usage Examples

Example 1: Basic Email Service

using System.Net;
using System.Net.Mail;

public class EmailService
{
    private readonly IConfiguration _configuration;

    public EmailService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public async Task SendEmailAsync(string to, string subject, string body)
    {
        string user = _configuration.GetValue<string>("MailSettings:Credentials:User");
        string password = _configuration.GetValue<string>("MailSettings:Credentials:Password");
        string host = _configuration.GetValue<string>("Server:Host");
        int port = _configuration.GetValue<int>("Server:Port");
        bool ssl = _configuration.GetValue<bool>("Server:Ssl");

        var mail = new MailMessage
        {
            From = new MailAddress(user),
            Subject = subject,
            Body = body,
            IsBodyHtml = true
        };
        mail.To.Add(to);

        using (var client = new SmtpClient(host, port))
        {
            client.EnableSsl = ssl;
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential(user, password);

            await client.SendMailAsync(mail);
        }
    }
}

Example 2: HTML Email with Template

public class EmailTemplateService
{
    private readonly IConfiguration _configuration;

    public EmailTemplateService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public async Task SendWelcomeEmailAsync(string to, string userName)
    {
        string htmlBody = $@"
            <html>
            <head>
                <style>
                    body {{ font-family: Arial, sans-serif; }}
                    .header {{ background-color: #4CAF50; color: white; padding: 20px; }}
                    .content {{ padding: 20px; }}
                </style>
            </head>
            <body>
                <div class='header'>
                    <h1>Welcome to Our Service!</h1>
                </div>
                <div class='content'>
                    <p>Hello {userName},</p>
                    <p>Thank you for registering with us.</p>
                    <p>Best regards,<br>The Team</p>
                </div>
            </body>
            </html>
        ";

        await SendEmailAsync(to, "Welcome!", htmlBody);
    }

    private async Task SendEmailAsync(string to, string subject, string body)
    {
        string user = _configuration.GetValue<string>("MailSettings:Credentials:User");
        string password = _configuration.GetValue<string>("MailSettings:Credentials:Password");
        string host = _configuration.GetValue<string>("Server:Host");
        int port = _configuration.GetValue<int>("Server:Port");
        bool ssl = _configuration.GetValue<bool>("Server:Ssl");

        var mail = new MailMessage
        {
            From = new MailAddress(user),
            Subject = subject,
            Body = body,
            IsBodyHtml = true
        };
        mail.To.Add(to);

        using (var client = new SmtpClient(host, port))
        {
            client.EnableSsl = ssl;
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential(user, password);

            await client.SendMailAsync(mail);
        }
    }
}

Example 3: Email with Attachments

public async Task SendEmailWithAttachmentAsync(string to, string subject, string body, string attachmentPath)
{
    string user = _configuration.GetValue<string>("MailSettings:Credentials:User");
    string password = _configuration.GetValue<string>("MailSettings:Credentials:Password");
    string host = _configuration.GetValue<string>("Server:Host");
    int port = _configuration.GetValue<int>("Server:Port");
    bool ssl = _configuration.GetValue<bool>("Server:Ssl");

    var mail = new MailMessage
    {
        From = new MailAddress(user),
        Subject = subject,
        Body = body,
        IsBodyHtml = true
    };
    mail.To.Add(to);

    // Add attachment
    if (File.Exists(attachmentPath))
    {
        var attachment = new Attachment(attachmentPath);
        mail.Attachments.Add(attachment);
    }

    using (var client = new SmtpClient(host, port))
    {
        client.EnableSsl = ssl;
        client.UseDefaultCredentials = false;
        client.Credentials = new NetworkCredential(user, password);

        await client.SendMailAsync(mail);
    }
}

Example 4: Multiple Recipients

public async Task SendBulkEmailAsync(List<string> recipients, string subject, string body)
{
    string user = _configuration.GetValue<string>("MailSettings:Credentials:User");
    string password = _configuration.GetValue<string>("MailSettings:Credentials:Password");
    string host = _configuration.GetValue<string>("Server:Host");
    int port = _configuration.GetValue<int>("Server:Port");
    bool ssl = _configuration.GetValue<bool>("Server:Ssl");

    var mail = new MailMessage
    {
        From = new MailAddress(user),
        Subject = subject,
        Body = body,
        IsBodyHtml = true
    };

    // Add multiple recipients
    foreach (var recipient in recipients)
    {
        mail.To.Add(recipient);
    }

    // Or use BCC for privacy
    // foreach (var recipient in recipients)
    // {
    //     mail.Bcc.Add(recipient);
    // }

    using (var client = new SmtpClient(host, port))
    {
        client.EnableSsl = ssl;
        client.UseDefaultCredentials = false;
        client.Credentials = new NetworkCredential(user, password);

        await client.SendMailAsync(mail);
    }
}

MailMessage Properties

Basic Properties

var mail = new MailMessage();
mail.From = new MailAddress("[email protected]", "Display Name");
mail.To.Add("[email protected]");
mail.Subject = "Email Subject";
mail.Body = "Email body content";
mail.IsBodyHtml = true;  // Enable HTML formatting

Advanced Properties

// Priority
mail.Priority = MailPriority.High;  // High, Normal, or Low

// CC and BCC
mail.CC.Add("[email protected]");
mail.Bcc.Add("[email protected]");

// Reply-To
mail.ReplyToList.Add("[email protected]");

// Headers
mail.Headers.Add("X-Custom-Header", "value");

Error Handling

Comprehensive Error Handling

[HttpPost]
public async Task<IActionResult> SendMail(string to, string asunto, string mensaje)
{
    try
    {
        if (string.IsNullOrWhiteSpace(to) || !IsValidEmail(to))
        {
            ViewData["ERROR"] = "Please provide a valid email address.";
            return View();
        }

        string user = configuration.GetValue<string>("MailSettings:Credentials:User");
        string password = configuration.GetValue<string>("MailSettings:Credentials:Password");

        if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password))
        {
            ViewData["ERROR"] = "Email configuration is missing.";
            return View();
        }

        var mail = new MailMessage
        {
            From = new MailAddress(user),
            Subject = asunto,
            Body = mensaje,
            IsBodyHtml = true,
            Priority = MailPriority.Normal
        };
        mail.To.Add(to);

        string host = configuration.GetValue<string>("Server:Host");
        int port = configuration.GetValue<int>("Server:Port");
        bool ssl = configuration.GetValue<bool>("Server:Ssl");

        using (var client = new SmtpClient(host, port))
        {
            client.EnableSsl = ssl;
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential(user, password);
            client.Timeout = 10000; // 10 seconds

            await client.SendMailAsync(mail);
        }

        ViewData["MENSAJE"] = "Email sent successfully.";
        return View();
    }
    catch (SmtpException ex)
    {
        ViewData["ERROR"] = $"SMTP Error: {ex.Message}";
        // Log the error
        return View();
    }
    catch (Exception ex)
    {
        ViewData["ERROR"] = $"Unexpected error: {ex.Message}";
        // Log the error
        return View();
    }
}

private bool IsValidEmail(string email)
{
    try
    {
        var addr = new MailAddress(email);
        return addr.Address == email;
    }
    catch
    {
        return false;
    }
}

Security Best Practices

Never commit credentials: Store passwords in User Secrets (development) or environment variables (production).

Using User Secrets (Development)

1

Initialize User Secrets

dotnet user-secrets init
2

Set secrets

dotnet user-secrets set "MailSettings:Credentials:User" "[email protected]"
dotnet user-secrets set "MailSettings:Credentials:Password" "your-app-password"
3

Access in code

Configuration automatically reads from User Secrets in development:
string user = configuration.GetValue<string>("MailSettings:Credentials:User");

Using Environment Variables (Production)

# Linux/macOS
export MailSettings__Credentials__User="[email protected]"
export MailSettings__Credentials__Password="your-app-password"

# Windows
setx MailSettings__Credentials__User "[email protected]"
setx MailSettings__Credentials__Password "your-app-password"

Using Azure Key Vault

// Program.cs
var builder = WebApplication.CreateBuilder(args);

if (builder.Environment.IsProduction())
{
    var keyVaultUrl = new Uri(builder.Configuration["KeyVaultUrl"]);
    builder.Configuration.AddAzureKeyVault(keyVaultUrl, new DefaultAzureCredential());
}

Testing Email Functionality

Using MailHog (Local SMTP Server)

{
  "Server": {
    "Host": "localhost",
    "Port": 1025,
    "Ssl": false,
    "DefaultCredentials": false
  },
  "MailSettings": {
    "Credentials": {
      "User": "test@localhost",
      "Password": ""
    }
  }
}
Run MailHog:
docker run -d -p 1025:1025 -p 8025:8025 mailhog/mailhog
# View emails at http://localhost:8025

Common Issues

Authentication Failed

Problem: “Authentication failed” error Solutions:
  • Verify username and password are correct
  • For Gmail: Use App Password instead of regular password
  • Check if 2FA is enabled and App Password is required
  • Ensure “Less secure app access” is enabled (if applicable)

Connection Timeout

Problem: “Unable to connect to remote server” Solutions:
  • Verify SMTP host and port are correct
  • Check firewall settings
  • Ensure SSL/TLS settings match server requirements
  • Try alternative ports (587, 465, 25)

SSL/TLS Errors

Problem: “The remote certificate is invalid” Solutions:
  • Set EnableSsl = true for ports 587 and 465
  • Verify server supports SSL/TLS
  • Update .NET runtime if certificate validation fails

Source Reference

  • MailsController: Controllers/MailsController.cs:7
  • SendMail action: Controllers/MailsController.cs:22
  • Configuration reading: Controllers/MailsController.cs:24

Build docs developers (and LLMs) love