Paw*_*wel 8 httpforbiddenhandler node.js mailgun nestjs
我尝试使用 mailgun 发送电子邮件。我使用 node.js (nest.js),这是我的邮件服务。我应该改变什么?当我尝试发送第一封电子邮件(mailgun 官方网站中的描述)时,我收到了相同的错误消息。
import { Injectable } from '@nestjs/common';
import * as Mailgun from 'mailgun-js';
import { IMailGunData } from './interfaces/mail.interface';
import { ConfigService } from '../config/config.service';
@Injectable()
export class MailService {
private mg: Mailgun.Mailgun;
constructor(private readonly configService: ConfigService) {
this.mg = Mailgun({
apiKey: this.configService.get('MAILGUN_API_KEY'),
domain: this.configService.get('MAILGUN_API_DOMAIN'),
});
}
send(data: IMailGunData): Promise<Mailgun.messages.SendResponse> {
console.log(data);
console.log(this.mg);
return new Promise((res, rej) => {
this.mg.messages().send(data, function (error, body) {
if (error) {
console.log(error);
rej(error);
}
res(body);
});
});
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试发送消息时,我收到带有禁止描述的 401 错误。
我的 mg (console.log(this.mg))
Mailgun {
username: 'api',
apiKey: '920d6161ca860e7b84d9de75e14exxx-xxx-xxx',
publicApiKey: undefined,
domain: 'lokalne-dobrodziejstwa.pl',
auth: 'api:920d6161ca860e7b84d9de75e14exxx-xxx-xxx',
mute: false,
timeout: undefined,
host: 'api.mailgun.net',
endpoint: '/v3',
protocol: 'https:',
port: 443,
retry: 1,
testMode: undefined,
testModeLogger: undefined,
options: {
host: 'api.mailgun.net',
endpoint: '/v3',
protocol: 'https:',
port: 443,
auth: 'api:920d6161ca860e7b84d9de75e14exxx-xxx-xxx',
proxy: undefined,
timeout: undefined,
retry: 1,
testMode: undefined,
testModeLogger: undefined
},
mailgunTokens: {}
}
Run Code Online (Sandbox Code Playgroud)
我的电子邮件正文
{
from: 'rejestracja@lokalne-dobrodziejstwa.pl',
to: 'me@gmail.com',
subject: 'Verify User',
html: '\n' +
' <h3>Hello me@gmail.com!</h3>\n' +
' '
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*Ben 42
当我的域位于欧盟区域时,我遇到了这个问题。当您使用欧盟区域时,您必须在配置中指定它 - Mailgun 没有明确解释。
所以它会是这样的:
var mailgun = require("mailgun-js")({
apiKey: API_KEY,
domain: DOMAIN,
host: "api.eu.mailgun.net",
});
Run Code Online (Sandbox Code Playgroud)
Joe*_*oep 14
欧盟用户:对于 mailgun v3,您必须在 url 选项中指定欧盟端点,mailgun.client()如下所示:
const API_KEY = "xxxxxxxxXxxxxxxxxxxxxxxxxxxx-xxxxxxx-xxxxxx";
const DOMAIN = "mydomaim.com";
const formData = require('form-data');
const Mailgun = require('mailgun.js');
const mailgun = new Mailgun(formData);
const client = mailgun.client({
username: 'api',
key: API_KEY,
url:"https://api.eu.mailgun.net"
});
// console.log(client)
const messageData = {
from: 'Yoopster <joep@mydomain.com>',
to: 'mybestbuddy@gmail.com',
subject: 'Hello',
text: 'Testing some Mailgun awesomeness!'
};
client.messages.create(DOMAIN, messageData)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
Run Code Online (Sandbox Code Playgroud)
小智 2
尝试通过控制台中的以下命令向自己发送电子邮件(帐户电子邮件):
curl -s --user 'api:YOUR_API_KEY' \
https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages \
-F from='Excited User <mailgun@YOUR_DOMAIN_NAME>' \
-F to=YOU@YOUR_DOMAIN_NAME \
-F to=bar@example.com \
-F subject='Hello' \
-F text='Testing some Mailgun awesomeness!'
Run Code Online (Sandbox Code Playgroud)
有效吗?
如果不是..我假设您已经正确编写了 api 和域,因此稍后如果您有免费帐户,您应该在概述部分检查授权收件人(您无法在试用帐户上向任何地方发送电子邮件,您必须先输入它)
如果您没有找到解决方案,这就是我完成邮件服务(工作)的方式,因此您可以尝试一下,我使用nodemailer来执行此操作:
import { Injectable, InternalServerErrorException, OnModuleInit } from '@nestjs/common';
import { readFileSync } from 'fs';
import { compile } from 'handlebars';
import { join } from 'path';
import * as nodemailer from 'nodemailer';
import { Options } from 'nodemailer/lib/mailer';
import * as mg from 'nodemailer-mailgun-transport';
import { IReplacement } from './replacements/replacement';
import { ResetPasswordReplacement } from './replacements/reset-password.replacement';
@Injectable()
export class MailService implements OnModuleInit {
private transporter: nodemailer.Transporter;
onModuleInit(): void {
this.transporter = this.getMailConfig();
}
sendResetPasswordMail(email: string, firstName: string = '', lastName: string = ''): void { // this is just example method with template but you can use sendmail directly from sendMail method
const resetPasswordReplacement = new ResetPasswordReplacement({
firstName,
lastName,
email,
});
this.sendMail(
proccess.env.MailBoxAddress),
email,
'Change password',
this.createTemplate('reset-password', resetPasswordReplacement),
);
}
sendMail(from: string, to: string, subject: string, body: string): void {
const mailOptions: Options = { from, to, subject, html: body };
return this.transporter.sendMail(mailOptions, (error) => {
if (error) {
throw new InternalServerErrorException('Error');
}
});
}
private getMailConfig(): any {
return nodemailer.createTransport(mg({
auth: {
api_key: proccess.env.MailApiKey,
domain: proccess.env.MailDomain
},
}));
}
private createTemplate(fileName: string, replacements: IReplacement): string {
const templateFile = readFileSync(join(__dirname, 'templates', `${fileName}.html`), { encoding: 'utf-8' });
const template = compile(templateFile);
return template(replacements);
}
}
Run Code Online (Sandbox Code Playgroud)
和
const templateFile = readFileSync(join(__dirname, 'templates', `${fileName}.html`), { encoding: 'utf-8' });
Run Code Online (Sandbox Code Playgroud)
定义包含内容的 html 文件的位置及其外观(在本例中为 Reset-password.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Password reset</title>
</head>
<body>
<div>Welcome {{firstName}} {{lastName}}</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
并且 {{}} 中的值将自动被库替换
在此示例中,ResetPasswordReplacement是它的唯一基本对象,其中包含 3 个属性,并且由空接口 IReplacement 继承 - 使其仅用于在模板文件中定义值
来源: