mail.ts 3.3 KB

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