mail.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. const nodemailer = require("nodemailer");
  2. const path = require("node:path");
  3. const fs = require("node:fs");
  4. const { resetMailText, verifyMailText, changeEmailText } = require("./text");
  5. const { CustomError } = require("../utils");
  6. const env = require("../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. // Read email templates
  20. const resetEmailTemplatePath = path.join(__dirname, "template-reset.html");
  21. const verifyEmailTemplatePath = path.join(__dirname, "template-verify.html");
  22. const changeEmailTemplatePath = path.join(__dirname,"template-change-email.html");
  23. let resetEmailTemplate,
  24. verifyEmailTemplate,
  25. changeEmailTemplate;
  26. // only read email templates if email is enabled
  27. if (env.MAIL_ENABLED) {
  28. resetEmailTemplate = fs
  29. .readFileSync(resetEmailTemplatePath, { encoding: "utf-8" })
  30. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  31. .replace(/{{site_name}}/gm, env.SITE_NAME);
  32. verifyEmailTemplate = fs
  33. .readFileSync(verifyEmailTemplatePath, { encoding: "utf-8" })
  34. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  35. .replace(/{{site_name}}/gm, env.SITE_NAME);
  36. changeEmailTemplate = fs
  37. .readFileSync(changeEmailTemplatePath, { encoding: "utf-8" })
  38. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  39. .replace(/{{site_name}}/gm, env.SITE_NAME);
  40. }
  41. async function verification(user) {
  42. if (!env.MAIL_ENABLED) {
  43. throw new Error("Attempting to send verification email but email is not enabled.");
  44. };
  45. const mail = await transporter.sendMail({
  46. from: env.MAIL_FROM || env.MAIL_USER,
  47. to: user.email,
  48. subject: "Verify your account",
  49. text: verifyMailText
  50. .replace(/{{verification}}/gim, user.verification_token)
  51. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  52. .replace(/{{site_name}}/gm, env.SITE_NAME),
  53. html: verifyEmailTemplate
  54. .replace(/{{verification}}/gim, user.verification_token)
  55. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  56. .replace(/{{site_name}}/gm, env.SITE_NAME)
  57. });
  58. if (!mail.accepted.length) {
  59. throw new CustomError("Couldn't send verification email. Try again later.");
  60. }
  61. }
  62. async function changeEmail(user) {
  63. if (!env.MAIL_ENABLED) {
  64. throw new Error("Attempting to send change email token but email is not enabled.");
  65. };
  66. const mail = await transporter.sendMail({
  67. from: env.MAIL_FROM || env.MAIL_USER,
  68. to: user.change_email_address,
  69. subject: "Verify your new email address",
  70. text: changeEmailText
  71. .replace(/{{verification}}/gim, user.change_email_token)
  72. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  73. .replace(/{{site_name}}/gm, env.SITE_NAME),
  74. html: changeEmailTemplate
  75. .replace(/{{verification}}/gim, user.change_email_token)
  76. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  77. .replace(/{{site_name}}/gm, env.SITE_NAME)
  78. });
  79. if (!mail.accepted.length) {
  80. throw new CustomError("Couldn't send verification email. Try again later.");
  81. }
  82. }
  83. async function resetPasswordToken(user) {
  84. if (!env.MAIL_ENABLED) {
  85. throw new Error("Attempting to send reset password email but email is not enabled.");
  86. };
  87. const mail = await transporter.sendMail({
  88. from: env.MAIL_FROM || env.MAIL_USER,
  89. to: user.email,
  90. subject: "Reset your password",
  91. text: resetMailText
  92. .replace(/{{resetpassword}}/gm, user.reset_password_token)
  93. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN),
  94. html: resetEmailTemplate
  95. .replace(/{{resetpassword}}/gm, user.reset_password_token)
  96. .replace(/{{domain}}/gm, env.DEFAULT_DOMAIN)
  97. });
  98. if (!mail.accepted.length) {
  99. throw new CustomError(
  100. "Couldn't send reset password email. Try again later."
  101. );
  102. }
  103. }
  104. async function sendReportEmail(link) {
  105. if (!env.MAIL_ENABLED) {
  106. throw new Error("Attempting to send report email but email is not enabled.");
  107. };
  108. const mail = await transporter.sendMail({
  109. from: env.MAIL_FROM || env.MAIL_USER,
  110. to: env.REPORT_EMAIL,
  111. subject: "[REPORT]",
  112. text: link,
  113. html: link
  114. });
  115. if (!mail.accepted.length) {
  116. throw new CustomError("Couldn't submit the report. Try again later.");
  117. }
  118. }
  119. module.exports = {
  120. changeEmail,
  121. verification,
  122. resetPasswordToken,
  123. sendReportEmail,
  124. }