如何使用 nodemailer 和 dreamhost 发送电子邮件(在 Node.js 服务器上)

How to send emails with nodemailer and dreamhost (on Node.js server)

我找不到任何特定于使用 nodemailer 从 dreamhost 发送电子邮件的有用帖子。我确实找到了一个 dreamhost article for sending emails via PHP,所以也许这可以帮助我们指明正确的方向...

无论哪种方式,这是我的 mailer.ts 文件:

import { createTransport, getTestMessageUrl } from "nodemailer";

import { frontendURL } from "./urls";

var transport = createTransport({
  host: "smtp.dreamhost.com",
  port: 465,
  auth: {
    user: encodeURIComponent(process.env.PROD_MAIL_USER),
    pass: encodeURIComponent(process.env.PROD_MAIL_PASS),
  },
  secure: true,
});

function generateHTML(resetToken: string) {
    return `
      <div>
        <h2>Hello from HaBits </h2>
        <p>
          Your <b>Password Reset Token</b> is here!
        </p>
        <h3>
          <a href="${frontendURL}/reset?token=${resetToken}" style="color: #75B748">Reset your password.</a>
        </h3>
        <p>HaBits ✅</p>
      </div>
    `;
}

export interface MailResponse {
  accepted?: string[] | null;
  rejected?: null[] | null;
  envelopeTime: number;
  messageTime: number;
  messageSize: number;
  response: string;
  envelope: Envelope;
  messageId: string;
}

export interface Envelope {
  from: string;
  to?: string[] | null;
}

export async function sendPasswordResetEmail(
  resetToken: string,
  to: string
): Promise<void> {
  // email the user a token
  const info = await transport.sendMail({
    to,
    from: process.env.PROD_MAIL_USER,
    subject: "✅ HaBits – password reset token",
    html: generateHTML(resetToken),
  });
}

生产中的错误响应:

{
    "errors": [
        {
            "message": "Invalid login: 535 5.7.8 Error: authentication failed: ",
            "locations": [
                {
                    "line": 2,
                    "column": 3
                }
            ],
            "path": [
                "sendUserPasswordResetLink"
            ],
            "extensions": {
                "code": "INTERNAL_SERVER_ERROR",
                "exception": {
                    "code": "EAUTH",
                    "response": "535 5.7.8 Error: authentication failed: ",
                    "responseCode": 535,
                    "command": "AUTH PLAIN",
                    "stacktrace": [
                        "Error: Invalid login: 535 5.7.8 Error: authentication failed: ",
                        "    at SMTPConnection._formatError (/workspace/backend/node_modules/nodemailer/lib/smtp-connection/index.js:784:19)",
                        "    at SMTPConnection._actionAUTHComplete (/workspace/backend/node_modules/nodemailer/lib/smtp-connection/index.js:1536:34)",
                        "    at SMTPConnection.<anonymous> (/workspace/backend/node_modules/nodemailer/lib/smtp-connection/index.js:540:26)",
                        "    at SMTPConnection._processResponse (/workspace/backend/node_modules/nodemailer/lib/smtp-connection/index.js:947:20)",
                        "    at SMTPConnection._onData (/workspace/backend/node_modules/nodemailer/lib/smtp-connection/index.js:749:14)",
                        "    at TLSSocket.SMTPConnection._onSocketData (/workspace/backend/node_modules/nodemailer/lib/smtp-connection/index.js:189:44)",
                        "    at TLSSocket.emit (node:events:390:28)",
                        "    at addChunk (node:internal/streams/readable:315:12)",
                        "    at readableAddChunk (node:internal/streams/readable:289:9)",
                        "    at TLSSocket.Readable.push (node:internal/streams/readable:228:10)",
                        "    at TLSWrap.onStreamRead (node:internal/stream_base_commons:199:23)"
                    ]
                }
            },
            "name": "GraphQLError"
        }
    ]
}

Dreamhost“支持”刚刚向我发送了关于 PHP 的文章,该文章建议使用 host: "ssl://smtp.dreamhost.com",但只是 returns 一个不太有用的“找不到地址”错误:

Error: getaddrinfo ENOTFOUND ssl://smtp.dreamhost.com

所以我非常有信心 nodemailer 配置是正确的 – 即。主机、端口、用户和密码

这是我自己的愚蠢错误‍♂️

这是用于在生产环境中发送电子邮件的 nodemailer 配置(假设您有一封由 dreamhost 托管的电子邮件):

import { createTransport, getTestMessageUrl } from "nodemailer";

var transport = createTransport({
  host: "smtp.dreamhost.com",
  port: 465,
  auth: {
    user: process.env.PROD_MAIL_USER, // your email address
    pass: process.env.PROD_MAIL_PASS, // your webmail password
  },
  secure: true,
  logger: true,
  debug: true,
});

// ...

await transport.sendMail({ ... })

我的问题是 encodeURIComponent() 包裹着我的电子邮件和密码 – 所以电子邮件 hello@example.com 被传递为 hello%40example.com

上面的 loggerdebugger 属性是可选的,但它们帮助我确定了服务器日志中的问题。