我正在尝试使用Gmail API在Node.js中创建一个简单的带有PDF附件的草稿。草稿被创建并在Gmail中显示,但它没有附件。此外,当在Gmail中点击草稿时,它会打开一个没有标题或内容的空草稿。当我尝试使用几乎相同的代码发送电子邮件时,它工作得很好。
这是我的代码:
const createMailEncodedMessage = async (params) => {
const msg = await buildMailBody(params)
// The body needs to be base64url encoded.
const encodedMessage = Buffer.from(msg)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '')
return encodedMessage
}
const sendEmail = async (params) => {
if (!auth) {
await init()
}
const encodedMessage = await createMailEncodedMessage(params)
return await gmail.users.messages.send({
userId: 'me',
requestBody: {
raw: encodedMessage,
},
})
}
const createDraft = async (params) => {
if (!auth) {
await init()
}
const encodedMessage = await createMailEncodedMessage(params)
return await gmail.users.drafts.create({
userId: 'me',
requestBody: {
message: {
raw: encodedMessage,
}
}
})
}
const buildMailBody = ({ from, to, subject, body, attachments }) => {
return new Promise((resolve, reject) => {
let mail = new MailComposer({
from,
to,
//text: 'I hope this works',
html: body,
subject,
textEncoding: 'base64',
attachments: attachments?.map(a => ({
filename: a.fileName,
content: fs.createReadStream(a.filePath),
})),
})
mail.compile().build((error, msg) => {
if (error) {
reject(error)
}
resolve(msg)
})
})
}
发布于 2021-08-11 01:09:41
在回顾了这个问题之后,我开发了一个代码,您可以使用它来实现您的目标。此脚本将发送一封带有两个示例附件的users.messages.send
电子邮件。我使用quickstart中描述的凭据流来管理令牌和作用域。请记住,您将需要一个方法来处理电子邮件MIME类型和base64转换。为了制作一个工作示例,我使用了MailComposer库来控制MIME类型。以下脚本应按原样工作,您只需设置凭据以使其运行(您可以使用快速入门中描述的步骤):
const fs = require('fs');
const readline = require('readline');
const {
google
} = require('googleapis');
const MailComposer = require('nodemailer/lib/mail-composer');
const SCOPES = ['https://mail.google.com/'];
const TOKEN_PATH = 'token.json';
fs.readFile('credentials.json', (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
authorize(JSON.parse(content), sendEmailWithAttachments);
});
function authorize(credentials, callback) {
const {
client_secret,
client_id,
redirect_uris
} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function getNewToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error retrieving access token',
err);
oAuth2Client.setCredentials(token);
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
function sendEmailWithAttachments(auth) {
let mail = new MailComposer({
to: "{ RECIPIENT EMAIL }",
text: "Morbi imperdiet gravida leo in commodo.",
html: "Morbi <i>imperdiet</i> gravida <b>leo</b> in commodo.",
subject: "Donec et porttitor erat",
textEncoding: "base64",
attachments: [{
filename: 'attachment1.txt',
content: 'UHJhZXNlbnQgc2VtcGVyIGF1Z3VlIHV0IGJpYmVuZHVtIHVsbGFtY29ycGVyLiBOdW5jIGluIG1hdXJpcyB1dCBxdWFtIHRyaXN0aXF1ZSBwcmV0aXVtIHF1aXMgZXQgbWkuIER1aXMgZW5pbSBsZW8sIGltcGVyZGlldCBxdWlzIHVybmEgZXUsIHBsYWNlcmF0IGZpbmlidXMgcXVhbS4gRXRpYW0gbWFzc2EgbG9yZW0sIHJ1dHJ1bSB2ZWwgc29kYWxlcyBhYywgYWNjdW1zYW4gZXQgcHVydXMuIFV0IG5lYyBsb3JlbSBpbnRlcmR1bSwgYWxpcXVhbSBuaXNpIGVnZXN0YXMsIGVnZXN0YXMgZWxpdC4gSW50ZWdlciB2ZWwgb3JuYXJlIGVyb3MsIGVnZXQgbGFjaW5pYSB2ZWxpdC4gRXRpYW0gZGlhbSBzZW0sIGFsaXF1YW0gYSBzb2xsaWNpdHVkaW4gdml0YWUsIHBvcnRhIGFjIGVsaXQuIEludGVyZHVtIGV0IG1hbGVzdWFkYSBmYW1lcyBhYyBhbnRlIGlwc3VtIHByaW1pcyBpbiBmYXVjaWJ1cy4gU3VzcGVuZGlzc2UgbmVjIGltcGVyZGlldCB1cm5hLiBTdXNwZW5kaXNzZSBhIGVzdCB1bHRyaWNpZXMsIHZlbmVuYXRpcyB1cm5hIGlkLCBzY2VsZXJpc3F1ZSBwdXJ1cy4gQWVuZWFuIHN1c2NpcGl0IGxhY3VzIHNlbSwgYXQgZWdlc3RhcyBhbnRlIGFsaXF1YW0gYXQu',
encoding: 'base64'
},
{
filename: 'attachment2.txt',
content: 'VmVzdGlidWx1bSBwdWx2aW5hciBzZW1wZXIgY29udmFsbGlzLiBPcmNpIHZhcml1cyBuYXRvcXVlIHBlbmF0aWJ1cyBldCBtYWduaXMgZGlzIHBhcnR1cmllbnQgbW9udGVzLCBuYXNjZXR1ciByaWRpY3VsdXMgbXVzLiBNYWVjZW5hcyBvcm5hcmUganVzdG8gc2VkIGFyY3UgaWFjdWxpcyBlZmZpY2l0dXIuIEZ1c2NlIHJob25jdXMsIGVzdCBmaW5pYnVzIGRpZ25pc3NpbSB2YXJpdXMsIHNhcGllbiB0dXJwaXMgcGxhY2VyYXQgcmlzdXMsIHNpdCBhbWV0IGZpbmlidXMgbmliaCBmZWxpcyBldSBsYWN1cy4gUHJvaW4gZWxlbWVudHVtLCBlcmF0IGEgYXVjdG9yIGx1Y3R1cywgcmlzdXMgb2RpbyBmcmluZ2lsbGEgcmlzdXMsIGlkIGNvbW1vZG8gbG9yZW0gdmVsaXQgaWQgbnVuYy4gRnVzY2Ugc2VkIHB1bHZpbmFyIG5pc2wsIGlkIGx1Y3R1cyBlcmF0LiBNYWVjZW5hcyBuZWMgY29uZGltZW50dW0gZmVsaXMuIE51bmMgZWxlbWVudHVtLCBqdXN0byBhIHZvbHV0cGF0IGJsYW5kaXQsIG1hZ25hIGlwc3VtIHBvcnRhIGFudGUsIHF1aXMgYmliZW5kdW0gbGVjdHVzIG9yY2kgdXQgbWF1cmlzLiBGdXNjZSBwdWx2aW5hciBmZWxpcyBhdCBudW5jIGNvbnNlY3RldHVyIGRpY3R1bS4gRXRpYW0gdmFyaXVzLCB0dXJwaXMgdGluY2lkdW50IHByZXRpdW0gcnV0cnVtLCBtZXR1cyBtYXVyaXMgbW9sZXN0aWUgZXgsIG5lYyBldWlzbW9kIGVuaW0ganVzdG8gYXQgZXN0Lg',
encoding: 'base64'
},
]
});
mail.compile().build((error, msg) => {
if (error) return console.log('ERROR - ' + error);
const encodedMessage = Buffer.from(msg).toString('base64').replace(
/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const gmail = google.gmail({
version: 'v1',
auth
});
gmail.users.messages.send({
userId: 'me',
resource: {
raw: encodedMessage,
}
}, (err, result) => {
if (err) return console.log('ERROR: ' + err);
console.log("Email sent: ", result.data);
});
})
}
该脚本分两个步骤工作。首先,它使用该库构建与标准MIME类型兼容的电子邮件。其次,它使用先前构建的电子邮件调用Gmail API。如果邮件发送成功,接口会返回邮件的ID和标签。如有疑问,请留言澄清。
https://stackoverflow.com/questions/68426653
复制相似问题