mail.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import nodemailer from "nodemailer";
  2. import path from "path";
  3. import fs from "fs";
  4. import { resetMailText, verifyMailText, changeEmailText } from "./text";
  5. import { CustomError } from "../utils";
  6. import env from "../env";
  7. const mailConfig = {
  8. host: env.MAIL_HOST,
  9. port: env.MAIL_PORT,
  10. secure: env.MAIL_SECURE,
  11. auth: env.MAIL_USER
  12. ? {
  13. user: env.MAIL_USER,
  14. pass: env.MAIL_PASSWORD
  15. }
  16. : undefined
  17. };
  18. const transporter = nodemailer.createTransport(mailConfig);
  19. export default transporter;
  20. // Read email templates
  21. const resetEmailTemplatePath = path.join(__dirname, "template-reset.html");
  22. const verifyEmailTemplatePath = path.join(__dirname, "template-verify.html");
  23. const changeEmailTemplatePath = path.join(
  24. __dirname,
  25. "template-change-email.html"
  26. );
  27. const resetEmailTemplate = fs
  28. .readFileSync(resetEmailTemplatePath, { encoding: "utf-8" })
  29. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  30. .replace(/{{site_name}}/gm, env.SITE_NAME);
  31. const verifyEmailTemplate = fs
  32. .readFileSync(verifyEmailTemplatePath, { encoding: "utf-8" })
  33. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  34. .replace(/{{site_name}}/gm, env.SITE_NAME);
  35. const changeEmailTemplate = fs
  36. .readFileSync(changeEmailTemplatePath, { encoding: "utf-8" })
  37. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  38. .replace(/{{site_name}}/gm, env.SITE_NAME);
  39. export const verification = async (user: User) => {
  40. const mail = await transporter.sendMail({
  41. from: env.MAIL_FROM || env.MAIL_USER,
  42. to: user.email,
  43. subject: "Verify your account",
  44. text: verifyMailText
  45. .replace(/{{verification}}/gim, user.verification_token)
  46. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  47. .replace(/{{site_name}}/gm, env.SITE_NAME),
  48. html: verifyEmailTemplate
  49. .replace(/{{verification}}/gim, user.verification_token)
  50. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  51. .replace(/{{site_name}}/gm, env.SITE_NAME)
  52. });
  53. if (!mail.accepted.length) {
  54. throw new CustomError("Couldn't send verification email. Try again later.");
  55. }
  56. };
  57. export const changeEmail = async (user: User) => {
  58. const mail = await transporter.sendMail({
  59. from: env.MAIL_FROM || env.MAIL_USER,
  60. to: user.change_email_address,
  61. subject: "Verify your new email address",
  62. text: changeEmailText
  63. .replace(/{{verification}}/gim, user.change_email_token)
  64. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  65. .replace(/{{site_name}}/gm, env.SITE_NAME),
  66. html: changeEmailTemplate
  67. .replace(/{{verification}}/gim, user.change_email_token)
  68. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  69. .replace(/{{site_name}}/gm, env.SITE_NAME)
  70. });
  71. if (!mail.accepted.length) {
  72. throw new CustomError("Couldn't send verification email. Try again later.");
  73. }
  74. };
  75. export const resetPasswordToken = async (user: User) => {
  76. const mail = await transporter.sendMail({
  77. from: env.MAIL_FROM || env.MAIL_USER,
  78. to: user.email,
  79. subject: "Reset your password",
  80. text: resetMailText
  81. .replace(/{{resetpassword}}/gm, user.reset_password_token)
  82. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN),
  83. html: resetEmailTemplate
  84. .replace(/{{resetpassword}}/gm, user.reset_password_token)
  85. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  86. });
  87. if (!mail.accepted.length) {
  88. throw new CustomError(
  89. "Couldn't send reset password email. Try again later."
  90. );
  91. }
  92. };