1.1.2 • Published 9 months ago

@acryps/mail v1.1.2

Weekly downloads
-
License
GPL-3.0-only
Repository
-
Last release
9 months ago

acryps mail

Component based queued mail handler

This package uses nodemailer.

When initializing a mailer you have to define a bunch of things right away.

MailTStoredMail, TStoredAddress
Sender addressEmail address to send from
Transport configurationNodemailer config for the mail transporter (It has no typings because nodemailer doesn't provide them in the first place)
Convert to sendable mailConvert TStoredMail into a sendable mail
CreateCreate TStoredMail and TStoredAddresses
Mark as sentMark TStoredMail as sent
Unsent queueOptional initial unsent TStoredMail queue (fetch from db)

These are the minimum requirements for a functional mailer. Optionally DKIM can be added to sign the mails in the headers and send error can be handled.

The mailer also supports localization via polyfills. Defining <div>{'Hello'.german('Hallo')}</div> in the component automatically translates according to the preferred language passed in the send method. Currently only german translation is supported and the tag to pass into the send method is hardcoded to de. This obviously isn't convenient and will be fixed soon.

Example usage:

Setup Mailer

const mailer = new Mailer<Mail, Address>(
	'example@domain.com', 

	// Transport configuration
	{
		host: 'smtp.host.com',
		port: 587,
		secure: false,
		auth: {
			user: 'example@domain.com',
			pass: 'securepassword1234'
		},
		tls: {
			rejectUnauthorized: false
		}
	}, 

	// Convert to sendable mail
	async model => {
		const recipients: string[] = await getRecipientEmails(model);

		return {
			subject: model.subject,
			text: model.text,
			html: model.html,
			recipients
		}
	},

	// Create
	async (addresses, mail) => {
		const model = new Mail();

		model.created = new Date();
		model.subject = mail.subject;
		model.text = mail.text;
		model.html = mail.html;

		await model.create();

		for (const address of addresses) {
			const mailAddress = new MailAddress();

			mailAddress.address = address;
			mailAddress.mail = model;

			await mailAddress.create();
		}

		return model;
	},
	
	// Mark as sent
	async model => {
		model.sent = new Date();
	
		await model.update();
	},

	// Unsent queue
	await db.mail.where(mail => mail.sent == null).toArray()
);

mailer.addDKIM(process.env.MAIL_DOMAIN, process.env.MAIL_DKIM_KEY);
mailer.onSendError = async (model, mail, error) => console.log(`Mail from ${mailer.sender} to ${mail.recipients} failed to send (id: ${model.id}):`, error);

Creating Mail Component

export class ExampleMail extends MailComponent {
	constructor(
		private fullname: string
	) {}

	render(child?: MailComponent): MailNode {
		return <html>
			<head>
				<meta charset="UTF-8" />
				<meta name="viewport" content="width=device-width,initial-scale=1" />
				<meta name="x-apple-disable-message-reformatting" />
			</head>
			<head>
				<style>...</style>
			</head>
			<body>
				<div class="line">Hello {this.fullname}</div>

				{child}

				<div class="line">Greetings</div>

				<div class="address">
					<div class="address-line">Name</div>
					<div class="address-line">Street</div>
					<div class="address-line">Place City</div>
				</div>

				<a href="mailto:example@domain.com">example@domain.com</a>
			</body>
			</html>;
	}
}

Sending Mail

// The passed address is of type TStoredAddress defined previously for the mailer.
mailer.send(new ExampleMail('Foo Bar'), address, 'de');

Sponsoring and support

This project is sponsored and supported by ACRYPS.

1.1.2

9 months ago

1.1.0

9 months ago

1.0.2

10 months ago

1.0.1

10 months ago

1.0.0

10 months ago