feat: replace maildev with mailpit
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful

This commit is contained in:
Aravinth Manivannan 2024-07-23 14:26:54 +05:30
parent 4cba4aac91
commit de5beb6dbd
Signed by: realaravinth
GPG key ID: F8F50389936984FF
3 changed files with 85 additions and 25 deletions

View file

@ -70,11 +70,15 @@ steps:
# #
services: services:
email: email:
image: maildev/maildev image: axllent/mailpit
environment: environment:
- MAILDEV_SMTP_PORT=10025 - MP_SMTP_AUTH=admin:password
- MAILDEV_INCOMING_USER=admin - MP_MAX_MESSAGES=5000
- MAILDEV_INCOMING_PASS=password - MP_SMTP_AUTH_ALLOW_INSECURE=1
- MP_SMTP_BIND_ADDR=0.0.0.0:10025
- MP_SMTP_AUTH_ALLOW_INSECURE=true
- MP_UI_BIND_ADDR=0.0.0.0:1080
database: database:
image: postgres image: postgres

View file

@ -2,14 +2,17 @@ version: "3"
services: services:
email: email:
image: maildev/maildev:latest image: axllent/mailpit
restart: always ports:
container_name: vanigam-dash-maildev - 1080:1080
network_mode: host - 10025:10025
environment: environment:
- MAILDEV_SMTP_PORT=10025 - MP_SMTP_AUTH=admin:password
- MAILDEV_INCOMING_USER=admin - MP_MAX_MESSAGES=5000
- MAILDEV_INCOMING_PASS=password - MP_SMTP_AUTH_ALLOW_INSECURE=1
- MP_SMTP_BIND_ADDR=0.0.0.0:10025
- MP_SMTP_AUTH_ALLOW_INSECURE=true
- MP_UI_BIND_ADDR=0.0.0.0:1080
postgres: postgres:
image: postgres:16.3 image: postgres:16.3

View file

@ -15,6 +15,7 @@ impl AccountValidationLinkOutMailerPort for LettreMailer {
first_name: &str, first_name: &str,
validation_secret: &str, validation_secret: &str,
) -> OutMailerPortResult<()> { ) -> OutMailerPortResult<()> {
// TODO: generate link from validation secret
let email = Message::builder() let email = Message::builder()
.from(self.from.parse().unwrap()) .from(self.from.parse().unwrap())
.reply_to(self.reply_to.parse().unwrap()) .reply_to(self.reply_to.parse().unwrap())
@ -40,21 +41,63 @@ mod tests {
use reqwest::Client; use reqwest::Client;
use url::Url; use url::Url;
use serde::Deserialize; use serde::{Deserialize, Serialize};
//#[derive(Deserialize, Clone)]
//struct MaildevAddress {
// address: String,
// name: String,
//}
//#[derive(Deserialize, Clone)]
//struct MaildevEmail {
// id: String,
// from: Vec<MaildevAddress>,
// to: Vec<MaildevAddress>,
// subject: String,
// text: String,
// html: Option<String>,
//}
#[derive(Deserialize, Clone)] #[derive(Deserialize, Clone)]
struct MaildevAddress { struct MailPitAddress {
#[serde(rename = "Address")]
address: String, address: String,
#[serde(rename = "Name")]
name: String, name: String,
} }
#[derive(Deserialize, Clone)] #[derive(Deserialize, Clone)]
struct MaildevEmail { pub struct MailpitSummary {
#[serde(rename = "ID")]
id: String, id: String,
from: Vec<MaildevAddress>, #[serde(rename = "To")]
to: Vec<MaildevAddress>, to: Vec<MailPitAddress>,
}
#[derive(Deserialize, Clone)]
pub struct MailpitEmail {
#[serde(rename = "From")]
from: MailPitAddress,
#[serde(rename = "To")]
to: Vec<MailPitAddress>,
#[serde(rename = "ReplyTo")]
reply_to: Vec<MailPitAddress>,
#[serde(rename = "Subject")]
subject: String, subject: String,
#[serde(rename = "Text")]
text: String, text: String,
html: Option<String>, #[serde(rename = "HTML")]
html: String,
}
#[derive(Deserialize, Clone)]
pub struct MailpitListEmails {
messages: Vec<MailpitSummary>,
}
#[derive(Serialize, Clone)]
pub struct MailpitDeleteEmail {
IDs: Vec<String>,
} }
#[actix_rt::test] #[actix_rt::test]
@ -77,21 +120,31 @@ mod tests {
let mut u = Url::parse(&maildev_url).unwrap(); let mut u = Url::parse(&maildev_url).unwrap();
u.set_path("/email"); u.set_path("/api/v1/messages");
let maildev_emails: Vec<MaildevEmail> = let mailpit_emails: MailpitListEmails =
c.get(u.clone()).send().await.unwrap().json().await.unwrap(); c.get(u.clone()).send().await.unwrap().json().await.unwrap();
let maildev_email = maildev_emails
let mailpit_summary = mailpit_emails
.messages
.iter() .iter()
.find(|e| e.to.iter().any(|f| f.address == email)) .find(|e| e.to.iter().any(|f| f.address == email))
.unwrap(); .unwrap();
assert!(maildev_email.text.contains(validation_secret));
assert!(maildev_email.text.contains(username)); u.set_path(&format!("/api/v1/message/{}", mailpit_summary.id));
assert!(maildev_email let mailpit_email: MailpitEmail =
c.get(u.clone()).send().await.unwrap().json().await.unwrap();
assert!(mailpit_email.text.contains(validation_secret));
assert!(mailpit_email.text.contains(username));
assert!(mailpit_email
.to .to
.iter() .iter()
.any(|t| t.address == email && t.name == username)); .any(|t| t.address == email && t.name == username));
u.set_path(&format!("/email/{}", maildev_email.id)); u.set_path("/api/v1/messages");
c.delete(u).send().await.unwrap(); let payload = MailpitDeleteEmail {
IDs: vec![mailpit_summary.id.clone()],
};
c.delete(u).json(&payload).send().await.unwrap();
} }
} }