Kodėl verta susipažinti su Mailgun
Kai pradedi kurti aplikaciją, kuri turi siųsti el. laiškus, greitai supranti, kad pats SMTP serveris – tai ne visada geriausias sprendimas. Serverio konfigūracija, IP reputacija, pristatymo statistika, spam filtrai – visa tai tampa tikra galvos skausmo priežastimi. Čia ir ateina į pagalbą tokie sprendimai kaip Mailgun.
Mailgun – tai transakcinio el. pašto API paslauga, kurią sukūrė Rackspace komanda, o vėliau įsigijo Pathwire. Jie specializuojasi būtent programinių laiškų siuntimui: patvirtinimo emailai, slaptažodžių keitimas, pranešimai, sąskaitos faktūros ir panašūs dalykai. Ne naujienlaiškiai ar marketingas (nors techniškai ir tai galima), bet būtent tie laiškai, kurie yra kritiniai tavo aplikacijos veikimui.
Kas man asmeniškai patinka Mailgun – jie turi nemokamą planą su 5000 laiškų per mėnesį pirmus tris mėnesius, o po to – 100 laiškų per dieną nemokamai. Vystant naują projektą tai puiki galimybė išbandyti visas funkcijas be jokių investicijų.
Paskyros sukūrimas ir pirmieji žingsniai
Registracija Mailgun platformoje yra ganėtinai paprasta, bet yra keletas niuansų, į kuriuos verta atkreipti dėmesį. Pirma, tau reikės patvirtinti savo telefono numerį – tai apsaugos mechanizmas nuo šlamšto siuntėjų. Antra, iškart po registracijos gausi sandbox domeną testavimui.
Sandbox domenas atrodo kažkaip taip: sandboxXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.mailgun.org. Juo gali siųsti laiškus tik į iš anksto patvirtintus el. pašto adresus. Tai puiku testavimui, bet produkcijai tikrai norėsi naudoti savo domeną.
Savo domeno pridėjimas reikalauja DNS įrašų konfigūravimo. Mailgun dashboard’e rasi visus reikalingus TXT, MX ir CNAME įrašus. Štai ką reikės pridėti:
- TXT įrašą SPF autentifikacijai
- TXT įrašą DKIM pasirašymui
- CNAME įrašą tracking funkcionalumui
- MX įrašus, jei nori gauti atsakymus į tą patį domeną
DNS propagacija gali užtrukti nuo kelių minučių iki 48 valandų, nors praktikoje paprastai viskas veikia per valandą ar dvi. Mailgun dashboard’e matysi verifikacijos statusą – kai viskas žalia, gali pradėti siųsti.
API raktas ir autentifikacija
Mailgun naudoja paprastą API key autentifikaciją. Rasi savo raktą Settings → API Keys sekcijoje. Yra du tipai raktų: Private API key ir Public validation key. Mums reikės Private rakto – jis suteikia pilną prieigą prie API.
Svarbu: niekada neįtraukite API rakto į viešą repository. Naudokite aplinkos kintamuosius arba secrets management sistemas. Jei atsitiktinai commitinai raktą į Git – nedelsiant jį pakeiskite Mailgun dashboard’e.
API raktas naudojamas kaip Basic Auth kredencialai, kur username visada yra api, o password – tavo API raktas. Daugelis HTTP bibliotekų tai palaiko natūraliai:
curl -s --user 'api:YOUR_API_KEY' \
https://api.mailgun.net/v3/YOUR_DOMAIN/messages \
-F from='[email protected]' \
-F to='[email protected]' \
-F subject='Hello' \
-F text='Testing some Mailgun awesomeness!'
Mailgun turi kelis API regionus: US (api.mailgun.net) ir EU (api.eu.mailgun.net). Jei tavo duomenys turi būti saugomi Europoje dėl GDPR ar kitų priežasčių, būtinai pasirink EU regioną registracijos metu.
Paprasto laiško siuntimas su Python
Python ekosistemoje Mailgun turi oficialią biblioteką, bet atvirai pasakius, ji nėra būtina. Galima puikiai verstis su requests biblioteka. Štai paprasčiausias pavyzdys:
import requests
def send_simple_message():
return requests.post(
"https://api.mailgun.net/v3/YOUR_DOMAIN/messages",
auth=("api", "YOUR_API_KEY"),
data={
"from": "Excited User
"to": ["[email protected]"],
"subject": "Hello",
"text": "Testing some Mailgun awesomeness!"
}
)
Kas man patinka šiame API – jis grąžina aiškius atsakymus. Sėkmės atveju gausi 200 statusą ir message ID, kurį galėsi naudoti tracking’ui. Klaidos atveju – aiškų pranešimą, kas negerai.
HTML laiškų siuntimas taip pat paprastas – tiesiog pridedi html parametrą šalia text. Rekomenduoju visada siųsti abi versijas: HTML vizualiai gražesnei versijai ir text kaip fallback senesnėms pašto programoms ar naudotojams, kurie išjungė HTML.
data={
"from": "Your App
"to": "[email protected]",
"subject": "Welcome to our service!",
"text": "Welcome! Thanks for signing up.",
"html": "
Welcome!
Thanks for signing up.
"
}
Node.js integracija ir praktiniai patarimai
JavaScript/Node.js pasaulyje situacija panaši. Yra oficiali mailgun-js biblioteka, bet ji šiek tiek pasenusi. Naujesnis variantas – mailgun.js, kuris palaiko modernų sintaksę ir promises.
const formData = require('form-data');
const Mailgun = require('mailgun.js');
const mailgun = new Mailgun(formData);
const mg = mailgun.client({
username: 'api',
key: process.env.MAILGUN_API_KEY,
url: 'https://api.mailgun.net' // arba api.eu.mailgun.net
});
mg.messages.create('YOUR_DOMAIN', {
from: "Excited User
to: ["[email protected]"],
subject: "Hello",
text: "Testing some Mailgun awesomeness!",
html: "
Testing some Mailgun awesomeness!
"
})
.then(msg => console.log(msg))
.catch(err => console.error(err));
Vienas dalykas, kurį pastebėjau praktikoje – verta implementuoti retry logiką. Kartais API gali grąžinti laikinų klaidų (500, 503), ir paprastas retry po kelių sekundžių paprastai išsprendžia problemą. Bet būk atsargus su rate limiting – Mailgun turi limitus pagal tavo planą.
Dar vienas patarimas: naudok template kintamuosius. Mailgun palaiko Handlebars sintaksę template’uose:
html: "
Hello {{name}}!
Your order #{{order_id}} has been confirmed.
",
"v:name": "John",
"v:order_id": "12345"
Bet atvirai, aš dažniau naudoju savo template sistemą (Jinja2 Python’e ar EJS Node’e) prieš siųsdamas į Mailgun. Tai suteikia daugiau kontrolės ir leidžia testuoti template’us lokaliai.
Priedai, inline paveikslėliai ir kiti triukai
Failų pridėjimas prie laiškų Mailgun’e yra intuityvus. Naudoji attachment parametrą ir perduodi failą. Python pavyzdys:
with open("document.pdf", "rb") as f:
requests.post(
"https://api.mailgun.net/v3/YOUR_DOMAIN/messages",
auth=("api", "YOUR_API_KEY"),
files=[("attachment", ("document.pdf", f.read(), "application/pdf"))],
data={
"from": "[email protected]",
"to": "[email protected]",
"subject": "Your document",
"text": "Please find attached document."
}
)
Inline paveikslėliai (tie, kurie rodomi tiesiog laiške, ne kaip priedai) reikalauja inline parametro ir CID (Content-ID) nuorodos HTML’e:
files=[("inline", ("logo.png", logo_data, "image/png"))],
data={
"html": '
'
}
Bet čia yra niuansas – ne visos pašto programos vienodai gerai palaiko inline paveikslėlius. Gmail dažnai juos blokuoja pagal nutylėjimą. Todėl produkcinėms aplikacijoms rekomenduoju:
- Hostuoti paveikslėlius CDN’e ir naudoti absoliučias nuorodas
- Naudoti inline tik logotipams ar kritiniams elementams
- Testuoti su skirtingomis pašto programomis (Gmail, Outlook, Apple Mail)
Webhook’ai ir event tracking
Viena galingiausių Mailgun funkcijų – webhook’ai. Jie leidžia gauti real-time pranešimus apie tai, kas vyksta su tavo laiškais: ar jie pristatyti, atidaryti, ar gavėjas paspaudė nuorodą, ar laiškas atmetamas.
Webhook’ų konfigūracija vyksta per dashboard: Settings → Webhooks. Gali pasirinkti, kokius event’us nori gauti:
- delivered – laiškas sėkmingai pristatytas
- opened – gavėjas atidarė laišką (reikalauja tracking)
- clicked – paspaudė nuorodą laiške
- bounced – laiškas atmestas (hard bounce)
- complained – pažymėtas kaip spam
- unsubscribed – gavėjas atsisakė prenumeratos
Webhook endpoint’as tavo pusėje gali atrodyti taip (Flask pavyzdys):
from flask import Flask, request
import hmac
import hashlib
app = Flask(__name__)
@app.route('/webhooks/mailgun', methods=['POST'])
def mailgun_webhook():
# Verifikuojame, kad request tikrai iš Mailgun
token = request.form.get('token')
timestamp = request.form.get('timestamp')
signature = request.form.get('signature')
signing_key = 'YOUR_WEBHOOK_SIGNING_KEY'
hmac_digest = hmac.new(
key=signing_key.encode(),
msg=f'{timestamp}{token}'.encode(),
digestmod=hashlib.sha256
).hexdigest()
if hmac_digest != signature:
return 'Invalid signature', 403
event = request.form.get('event')
recipient = request.form.get('recipient')
# Čia tavo logika: atnaujink duombazę, siųsk analytics, etc.
print(f"Event: {event} for {recipient}")
return 'OK', 200
Signature verifikacija yra kritinė – be jos bet kas galėtų siųsti fake webhook’us į tavo sistemą. Mailgun signing key rasi dashboard’e šalia webhook nustatymų.
Praktinis patarimas: webhook’ai turėtų būti asinchroniniai. Jei webhook handler’is daro sunkias operacijas (duombazės update’ai, išoriniai API call’ai), geriau juos įdėti į queue (Celery, RabbitMQ, Redis Queue) ir grąžinti atsakymą Mailgun kuo greičiau. Jei Mailgun negauna atsakymo per kelias sekundes, jis bandys siųsti webhook dar kartą.
Batch siuntimas ir optimizacija
Kai reikia išsiųsti daug laiškų (pavyzdžiui, pranešimus visiems naudotojams), yra keletas strategijų. Pats paprasčiausias būdas – loop’as su individualiais API call’ais. Bet tai neefektyvu ir lėta.
Mailgun palaiko recipient variables funkcionalumą, leidžiantį siųsti personalizuotus laiškus vienoje užklausoje:
mg.messages.create('YOUR_DOMAIN', {
from: "[email protected]",
to: ["[email protected]", "[email protected]", "[email protected]"],
subject: "Hello %recipient.name%",
text: "Hi %recipient.name%, your balance is %recipient.balance%",
"recipient-variables": JSON.stringify({
"[email protected]": {"name": "John", "balance": "$100"},
"[email protected]": {"name": "Jane", "balance": "$250"},
"[email protected]": {"name": "Bob", "balance": "$50"}
})
});
Kiekvienas gavėjas gaus personalizuotą laišką, bet tai bus viena API užklausa. Limitas – 1000 gavėjų per užklausą.
Dar vienas optimizavimo aspektas – rate limiting. Priklausomai nuo plano, Mailgun leidžia siųsti tam tikrą kiekį laiškų per valandą. Jei viršiji limitą, gausi 429 statusą. Čia verta implementuoti exponential backoff:
import time
def send_with_retry(send_function, max_retries=3):
for attempt in range(max_retries):
try:
response = send_function()
if response.status_code == 200:
return response
elif response.status_code == 429:
wait_time = 2 ** attempt # 1s, 2s, 4s
time.sleep(wait_time)
else:
return response
except Exception as e:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)
return None
Ko išmokau integruojant Mailgun realiuose projektuose
Po kelių metų darbo su Mailgun įvairių dydžių projektuose, turiu kelias mintis, kuriomis norėčiau pasidalinti.
Pirma, visada testuok su tikrais el. pašto adresais prieš paleidžiant produkciją. Sandbox puikus pradžiai, bet tikras domenas su tikrais gavėjais gali atskleisti problemų, kurių nematei sandbox’e. Pavyzdžiui, kai kurie ISP (Internet Service Providers) turi griežtesnius spam filtrus nei kiti.
Antra, monitork savo pristatymo statistiką. Mailgun dashboard’as rodo delivery rate, bounce rate, complaint rate. Jei bounce rate viršija 5%, tai raudona vėliavėlė – galbūt tavo el. pašto sąrašas pasenęs arba yra duomenų kokybės problemų. Complaint rate (spam skundimai) turėtų būti žemiau 0.1%. Jei didesnis – peržiūrėk savo turinį ir siuntimo praktikas.
Trečia, naudok subaccounts dideliems projektams. Jei turi kelis produktus ar klientus, subaccounts leidžia atskirti jų statistiką, limitus ir billing’ą. Tai ypač svarbu, jei kuri SaaS platformą.
Ketvirta, suprojektuok savo sistemą taip, kad galėtum pakeisti el. pašto providerį. Nepriklausyk per daug nuo Mailgun specifinių funkcijų. Turėk abstraction layer’į, kuris galėtų būti lengvai pakeistas į SendGrid, AWS SES ar kitą sprendimą. Tai gali atrodyti kaip over-engineering, bet kai staiga reikia migruoti (dėl kainų, funkcionalumo ar bet kokios kitos priežasties), būsi dėkingas sau.
Penkta, el. pašto pristatymas nėra momentinis. Netgi su Mailgun, kuris yra greitas, gali praeiti kelios sekundės ar net minutės, kol laiškas pasieks gavėją. Tai priklauso nuo gavėjo pašto serverio, queue’ų, spam filtrų. Todėl projektavimo lygmenyje nedaryk prielaidų, kad laiškas bus pristatytas iškart. Naudok webhook’us, kad sužinotum realų statusą.
Šešta, GDPR ir privatumas. Jei dirbi su Europos naudotojais, įsitikink, kad naudoji EU regioną. Taip pat turėk mechanizmą, kaip ištrinti naudotojo duomenis iš Mailgun, kai jis to prašo. Mailgun saugo logs ir event data tam tikrą laiką – peržiūrėk jų retention policy ir įsitikink, kad tai atitinka tavo privatumo politiką.
Septinta, kainų optimizavimas. Mailgun kainodara paprasta – moki už išsiųstus laiškus. Bet yra niuansų: validacija (email verification API) kainuoja atskirai, saugojimas (jei nori saugoti laiškų kopijas ilgiau) taip pat. Jei siunti daug laiškų, verta derėtis dėl enterprise plano – gali gauti geresnę kainą.
Aštunta, ir gal svarbiausia – el. paštas yra sudėtingas. Netgi su tokiu patikimu įrankiu kaip Mailgun, dalys laiškų nepasieks gavėjų. Tai normalu. Projektavimo lygmenyje turėk backup planus: jei kritinis laiškas (pavyzdžiui, slaptažodžio keitimas) nepristatytas, leisk naudotojui prašyti pakartotinai. Netgi geriausi provideriai negali garantuoti 100% pristatymo – per daug kintamųjų, kurių jie nekontroliuoja.
Mailgun yra solidus įrankis transakciniams laiškams. API paprastas, dokumentacija gera, palaikymas (bent mano patirtyje) reaguoja greitai. Taip, yra alternatyvų – SendGrid, AWS SES, Postmark – ir kiekvienas turi savo privalumų. Bet jei ieškote patikimo, developer-friendly sprendimo su protinga kainodara, Mailgun tikrai vertas dėmesio. Pradėk nuo nemokamo plano, išbandyk su savo projektu, ir greičiausiai rasi, kad tai viskas, ko tau reikia.

