Kirim Email Transaksional dengan ASP.NET Core dan MailAnvil (C#)
Backend fintech dan enterprise Indonesia masih banyak pakai .NET. Sayangnya provider email API populer seperti SendGrid atau Mailgun butuh kartu kredit untuk top-up — hambatan nyata buat developer lokal. Tutorial ini menunjukkan cara integrasi MailAnvil ke aplikasi ASP.NET Core, dengan QRIS/GoPay sebagai metode bayar dan harga IDR 2,4x lebih murah di volume 50 ribu email/bulan.
Kenapa MailAnvil untuk ASP.NET Core?
| Fitur | MailAnvil | SendGrid | Mailgun |
|---|---|---|---|
| Harga 10K/bulan | Rp 149rb | $20 (~Rp 320rb) | $35 (~Rp 560rb) |
| Bayar pakai | QRIS, GoPay | Kartu kredit | Kartu kredit |
| Latency dari Jakarta | ~10ms (CF edge) | ~180ms (US relay) | ~200ms (US relay) |
| MCP server | Native | Community | Community |
| Docs Bahasa | Ya | Tidak | Tidak |
Setup Project
dotnet new webapi -n MailAnvilEmailApp
cd MailAnvilEmailApp
HttpClient sudah bawaan .NET — tidak perlu library tambahan.
Simpan API key di appsettings.json (atau environment variable untuk production):
{
"MailAnvil": {
"ApiKey": "re_xxxxxxxxxxxxxxxx"
}
}
Service Class
Buat file Services/MailAnvilService.cs:
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
public class MailAnvilService
{
private readonly HttpClient _http;
private readonly string _apiKey;
public MailAnvilService(HttpClient http, IConfiguration config)
{
_http = http;
_apiKey = config["MailAnvil:ApiKey"]
?? throw new InvalidOperationException("MAILANVIL_API_KEY tidak diset");
_http.BaseAddress = new Uri("https://api.mailanvil.com/v1/");
_http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", _apiKey);
}
public async Task<JsonElement> SendEmailAsync(string to, string subject, string html)
{
var payload = JsonSerializer.Serialize(new
{
from = "[email protected]",
to,
subject,
html
});
using var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await _http.PostAsync("send", content);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(
$"MailAnvil send gagal: {(int)response.StatusCode} {body}");
return JsonSerializer.Deserialize<JsonElement>(body);
}
}
Registrasi DI
Di Program.cs:
builder.Services.AddHttpClient<MailAnvilService>();
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
AddHttpClient memakai IHttpClientFactory — koneksi reuse, tidak ada socket exhaustion.
Contoh: Kirim OTP
Buat Controllers/OtpController.cs:
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/otp")]
public class OtpController : ControllerBase
{
private readonly MailAnvilService _mail;
public OtpController(MailAnvilService mail) => _mail = mail;
[HttpPost("kirim")]
public async Task<IActionResult> KirimOtp([FromBody] KirimOtpRequest req)
{
var kode = Random.Shared.Next(100000, 999999).ToString();
var html = $@"
<div style=""font-family: Arial, sans-serif; max-width: 400px; margin: 0 auto;"">
<h2>Kode Verifikasi Anda</h2>
<p>Kode OTP Anda: <strong style=""font-size: 24px; color: #ff801f;"">{kode}</strong></p>
<p>Kode ini berlaku selama 5 menit. Jangan bagikan kode ini kepada siapa pun.</p>
</div>";
await _mail.SendEmailAsync(req.Email, "Kode Verifikasi Anda", html);
return Ok(new { terkirim = true });
}
}
public record KirimOtpRequest(string Email);
Simpan kode OTP di Redis/cache dengan TTL 5 menit, bandingkan saat user submit. Jangan kirim ulang lebih dari 3x per jam — throttle rate limit di level aplikasi.
Penanganan Error
Dua kelas error yang perlu dibedakan:
- 4xx — payload salah atau API key invalid. Jangan retry; perbaiki request.
- 5xx / timeout — upstream sementara. Retry dengan exponential backoff maksimal 3x.
for (int attempt = 1; attempt <= 3; attempt++)
{
try
{
await _mail.SendEmailAsync(to, subject, html);
break;
}
catch (HttpRequestException) when (attempt < 3)
{
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}
}
Verifikasi Domain
Sebelum production, verifikasi domain pengirim di dashboard MailAnvil (app.mailanvil.com):
- Tambahkan domain → MailAnvil generate record DNS SPF, DKIM, DMARC.
- Pakai Cloudflare DNS? DKIM di-setup otomatis — tidak perlu copy-paste record manual.
- Tunggu verifikasi (biasanya < 5 menit).
Domain belum verifikasi = email masuk spam atau ditolak. Jangan skip langkah ini.
Langkah Berikutnya
- Webhook untuk tracking status email (delivered, bounced): lihat artikel webhook HMAC kami.
- Suppression list otomatis untuk alamat yang hard bounce.
- Dokumentasi lengkap: docs.mailanvil.com