Why can't I send emails through amazon ses on Node? - node.js

I'm using "aws-sdk": "^2.117.0", my code looks like this:
var AWS = require('aws-sdk');
exports.sendAWSMail = function(message, destination){
const ses = new AWS.SES();
// http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SES.html#sendEmail-property
const sendEmail = ses.sendEmail;
var data = {
Destination: {
ToAddresses: [
"blahblah#gmail.com"
]
},
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: "This message body contains HTML formatting. It can, for example, contain links like this one: <a class=\"ulink\" href=\"http://docs.aws.amazon.com/ses/latest/DeveloperGuide\" target=\"_blank\">Amazon SES Developer Guide</a>."
},
Text: {
Charset: "UTF-8",
Data: "This is the message body in text format."
}
},
Subject: {
Charset: "UTF-8",
Data: "Test email"
}
},
Source: "no-reply#frutacor.com.br",
}
sendEmail(data)
}
But I get this error:
TypeError: this.makeRequest is not a function
at svc.(anonymous function) (/Users/iagowp/Desktop/trampos/frutacor/node_modules/aws-sdk/lib/service.js:499:23)
I didn't find any Node examples at their website, but from what I've seen elsewhere (like here), it looks correct. What am I doing wrong?

The main problem is in line #5 and it's always a good idea to add the callback function for logging errors and successful requests.
var AWS = require('aws-sdk');
exports.sendAWSMail = function(message, destination){
const ses = new AWS.SES();
var data = {
Destination: {
ToAddresses: [
"blahblah#gmail.com"
]
},
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: "This message body contains HTML formatting. It can, for example, contain links like this one: <a class=\"ulink\" href=\"http://docs.aws.amazon.com/ses/latest/DeveloperGuide\" target=\"_blank\">Amazon SES Developer Guide</a>."
},
Text: {
Charset: "UTF-8",
Data: "This is the message body in text format."
}
},
Subject: {
Charset: "UTF-8",
Data: "Test email"
}
},
Source: "no-reply#frutacor.com.br",
}
ses.sendEmail(data, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
}

Related

How to send PDF file object from Facebook messaging API

I have developed a facebook messenger app in Node.js.
I am using PDFKit to generate a PDF and send it to the user from the messenger bot. The problem I am facing is I am not able to send the generated file object.
generatePDF.js
require('dotenv').config("./env");
const getStream = require('get-stream')
const PDFDocument = require('pdfkit');
const fs = require('fs');
async function createPDF(name) {
const doc = new PDFDocument({
layout: 'landscape',
size: 'A4',
});
doc.rect(0, 0, doc.page.width, doc.page.height).fill('#fff');
``
doc.fontSize(10);
doc.image('src/airtable/assets/corners.png', -1, 0, { scale: 0.585 }, { fit: [doc.page.width, doc.page.height], align: 'center' })
doc
.font('src/airtable/fonts/Pinyon Script 400.ttf')
.fontSize(65)
.fill('#125951')
.text(`${name}`, 240, 240, {
// width: 500,
// align: 'center'
});
doc.end();
return await getStream.buffer(doc)
}
module.exports = { createPDF}
Invoking the above function after receiving specific postback
main.js
const pdf= require('./generatePDF')
name = "John"
const generated_pdf = await pdf.createPDF(name)
sendMedia(sender_psid, generated_pdf )
async function sendMedia(sender_psid, file) {
try {
let response = {
"attachment": {
"type": "file",
"payload": file
}
}
}
callSendAPI(sender_psid, response);
}
catch (e) {
console.log("Error cert ", e)
}
}
function callSendAPI(sender_psid, response) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
};
// Send the HTTP request to the Messenger Platform
request({
"uri": "https://graph.facebook.com/v7.0/me/messages",
"qs": { "access_token": process.env.FB_PAGE_TOKEN },
"method": "POST",
"json": request_body
}, (err, res, body) => {
if (!err) {
console.log('message sent!!!');
} else {
console.error("Unable to send message:" + err);
}
});
}
How can I send the file object without a URL and without fetching locally?
any help or advice is appreciated!
There is no such type ("application/pdf"), for sending attachments like a PDF you'd use the file type. Also, as stated in the docs, there is no "filedata" parameter, instead you'd use "payload".
Docs can be found here by the way:
https://developers.facebook.com/docs/messenger-platform/reference/send-api/

How to send Javascript Object as readable JSON in Slack API?

I am trying to send a formatted JS object on Slack using the API.
Best I could do was sending to chat.postMessage as:
const testObj = {a: "Hello", b: "World"};
...
data: {
channel: "#my-channel"
text: JSON.stringify(testObj, null, "\t")
}
But it's still not formatted well and can't be minimized like JSON file on Slack.
How can I send it better formatted or as a JSON file?
I would recommend you to use the Text Snippet feature via files.upload method, so you can format the content type properly, in this case javascript.
Send Slack Text Snippet                                                                                
Run in Fusebit
const testObj = {a: "Hello", b: "World"};
const result = await slackClient.files.upload({
channels: slackUserId,
content: testObj,
title: 'Sample',
filetype: 'javascript'
});
const {name, pretty_type} = result.file;
ctx.body = { message: `Successfully sent a text snippet of type ${pretty_type} called ${name} to Slack user ${slackUserId}!` };
I found a good working solution using only native node libraries to get nicely formatted JSON file.
Here's the full code, replace contentObj with whatever object you want to convert to JSON.
Put your designed channel and bot auth token
const https = require('https')
const contentObj = {a: "hello", b: "world"}
const formObject = {
channels: "#myChannel",
content: JSON.stringify(contentObj, null, 2),
filename: "myFile.json",
initial_comment:
"Hello World from JSON HTTPS!",
title: "myFile.json",
};
const urlencodedForm = new URLSearchParams(
Object.entries(formObject)
).toString();
const options = {
hostname: "slack.com",
port: 443,
path: "/api/files.upload",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": urlencodedForm.length,
Authorization: "Bearer " + "Bot Token",
},
};
const req = https.request(options, function (res) {
let responseBody = "";
res.on("data", function (chunk) {
responseBody += chunk;
});
res.on("end", () => {
const finalResponse = JSON.parse(responseBody);
if (finalResponse.ok) {
console.log("successfully sent msg to slack");
} else {
console.log("Message Failed");
}
});
});
req.on("error", (error) => {
console.error(error);
});
req.write(urlencodedForm);
req.end();

How to dynamically set aws ses TemplateData using node.js?

I'm trying to send an email with custom data.
async function sendEmailToSalesTeamOnBookingDemoClass(email,name,phoneNumber,utmSource,utmTerm,utmMedium,deviceType,browser,referrer) {
try {
let emailMe = "abc#gmail.com"
const ses = new AWS.SES({ apiVersion: "2010-12-01" });
const params = {
Destination: {
ToAddresses: [emailMe]
},
Source: senderEmail,
Template: "Sales_Email_Demo",
TemplateData : JSON.stringify({
"name": name,
"email": email,
"phone": phoneNumber,
"utmSource":utmSource,
"utmTerm":utmTerm,
"utmMedium":utmMedium,
"browser":browser,
"referrer":referrer,
"deviceType":deviceType
}),
Tags: [
{
Name: 'SomeName',
Value: 'info'
}
]
};
const sendEmailReceiver = ses.sendTemplatedEmail(params).promise();
sendEmailReceiver
.then(data => {
console.log(senderEmail,emailMe)
console.log("Email submitted to SES", data);
})
.catch(error => {
console.log("Email not submitted to SES:" + error);
});
}
catch (e) {
console.error(`Error: ${e}`);
}
}
The response says that the email was sent successfully.
Email submitted to SES {
ResponseMetadata: { RequestId: 'c08b9948-7be3-465d-a72c-fcca23f9f059' },
MessageId: '010901793bd95a02-813072dc-bb87-4b65-91c4-03f7f29dcbd0-000000'
}
But there is no email received even though the sender email has been verified and tested. Is there something wrong with my template?
{
"Template": {
"TemplateName": "Sales_Email_Demo",
"SubjectPart": "some subject!",
"HtmlPart": "<html> <body><p>Hello,</p><p>Details:</p><p>Name:{{name}}</p><p>Phone Number: {{phoneNumber}}</p><p>Email Id: {{emailId}}</p><p>Source: {{utmSource}}</p><p>Medium: {{utmMedium}}</p><p>Term:{{utmTerm}}</p><p>Device:{{deviceType}}</p><p>Browser:{{browser}}</p><p>Referrer: {{referrer}}</p></body></html>"
}
}
I figured it out. The issue was with the template. The sending and receiving variables were named differently.

How to change the Email FROM Name with NodeJs aws-sdk

I am sending Emails via the aws-sdk for Nodejs like this:
const params = {
Destination: {
ToAddresses: [... ],
},
Message: {
Body: {
Html: {
Data: `...`,
Charset: 'utf-8'
},
},
Subject: {
Data: `...`,
Charset: 'utf-8'
}
},
Source: 'support#mydomain.com',
ReturnPath: 'support#mydomain.com',
};
awsConfig.ses.sendEmail(params, (err, data))
The received email looks like this in Gmail:
However, I want to know how to change this name:
Currently the from name is support, because the from email is support#mydomain.com. But I want it to be replaced by the company like GitHub below.
Thanks in advance for any help!
Here is what I ended up doing:
I set the Source attribute in the params to
'CompanyName <support#mydomain.com>'
Thanks to #Neil Lunn
You can use this syntax
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'REGION'});
// Create sendEmail params
var params = {
Destination: { /* required */
CcAddresses: [
'EMAIL_ADDRESS',
/* more items */
],
ToAddresses: [
'EMAIL_ADDRESS',
/* more items */
]
},
Message: { /* required */
Body: { /* required */
Html: {
Charset: "UTF-8",
Data: "HTML_FORMAT_BODY"
},
Text: {
Charset: "UTF-8",
Data: "TEXT_FORMAT_BODY"
}
},
Subject: {
Charset: 'UTF-8',
Data: 'Test email'
}
},
Source: 'SENDER_EMAIL_ADDRESS', /* required */
ReplyToAddresses: [
'EMAIL_ADDRESS',
/* more items */
],
};
// Create the promise and SES service object
var sendPromise = new AWS.SES({apiVersion: '2010-12-01'}).sendEmail(params).promise();
// Handle promise's fulfilled/rejected states
sendPromise.then(
function(data) {
console.log(data.MessageId);
}).catch(
function(err) {
console.error(err, err.stack);
});

How to attach file to an email with nodemailer

I have code that send email with nodemailer in nodejs but I want to attach file to an email but I can't find way to do that I search on net but I could't find something useful.Is there any way that I can attach files to with that or any resource that can help me to attach file with nodemailer?
var nodemailer = require('nodemailer');
var events = require('events');
var check =1;
var events = new events.EventEmitter();
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "gmail",
auth: {
user: "example#gmail.com",
pass: "pass"
}
});
function inputmail(){
///////Email
const from = 'example<example#gmail.com>';
const to = 'example#yahoo.com';
const subject = 'example';
const text = 'example email';
const html = '<b>example email</b>';
var mailOption = {
from: from,
to: to,
subject: subject,
text: text,
html: html
}
return mailOption;
}
function send(){
smtpTransport.sendMail(inputmail(),function(err,success){
if(err){
events.emit('error', err);
}
if(success){
events.emit('success', success);
}
});
}
///////////////////////////////////
send();
events.on("error", function(err){
console.log("Mail not send");
if(check<10)
send();
check++;
});
events.on("success", function(success){
console.log("Mail send");
});
Include in the var mailOption the key attachments, as follow:
var mailOptions = {
...
attachments: [
{ // utf-8 string as an attachment
filename: 'text1.txt',
content: 'hello world!'
},
{ // binary buffer as an attachment
filename: 'text2.txt',
content: new Buffer('hello world!','utf-8')
},
{ // file on disk as an attachment
filename: 'text3.txt',
path: '/path/to/file.txt' // stream this file
},
{ // filename and content type is derived from path
path: '/path/to/file.txt'
},
{ // stream as an attachment
filename: 'text4.txt',
content: fs.createReadStream('file.txt')
},
{ // define custom content type for the attachment
filename: 'text.bin',
content: 'hello world!',
contentType: 'text/plain'
},
{ // use URL as an attachment
filename: 'license.txt',
path: 'https://raw.github.com/andris9/Nodemailer/master/LICENSE'
},
{ // encoded string as an attachment
filename: 'text1.txt',
content: 'aGVsbG8gd29ybGQh',
encoding: 'base64'
},
{ // data uri as an attachment
path: 'data:text/plain;base64,aGVsbG8gd29ybGQ='
}
]}
Choose the option that adjust to your needs.
Link:Nodemailer Repository GitHub
Good Luck!!
Your code is almost right, just need to add, "attachments" property for attaching the files in your mail,
YOUR mailOption:
var mailOption = {
from: from,
to: to,
subject: subject,
text: text,
html: html
}
Just add attachments like
var mailOption = {
from: from,
to: to,
subject: subject,
text: text,
html: html,
attachments: [{
filename: change with filename,
path: change with file path
}]
}
attachments also provide some other way to attach file for more information check nodemailer community's documentation HERE
If you are passing options object in mail composer constructor and attachment is on http server then it should look like:
const options = {
attachments = [
{ // use URL as an attachment
filename: 'xxx.jpg',
path: 'http:something.com/xxx.jpg'
}
]
}
var express = require('express');
var router = express(),
multer = require('multer'),
upload = multer(),
fs = require('fs'),
path = require('path');
nodemailer = require('nodemailer'),
directory = path.dirname("");
var parent = path.resolve(directory, '..');
// your path to store the files
var uploaddir = parent + (path.sep) + 'emailprj' + (path.sep) + 'public' + (path.sep) + 'images' + (path.sep);
/* GET home page. */
router.get('/', function(req, res) {
res.render('index.ejs', {
title: 'Express'
});
});
router.post('/sendemail', upload.any(), function(req, res) {
var file = req.files;
console.log(file[0].originalname)
fs.writeFile(uploaddir + file[0].originalname, file[0].buffer, function(err) {
//console.log("filewrited")
//console.log(err)
})
var filepath = path.join(uploaddir, file[0].originalname);
console.log(filepath)
//return false;
nodemailer.mail({
from: "yourgmail.com",
to: req.body.emailId, // list of receivers
subject: req.body.subject + " ✔", // Subject line
html: "<b>" + req.body.description + "</b>", // html body
attachments: [{
filename: file[0].originalname,
streamSource: fs.createReadStream(filepath)
}]
});
res.send("Email has been sent successfully");
})
module.exports = router;
attachments: [
{
filename: "inovices_1.pdf", // the file name
path: "https://*************************/invoice/10_9_RMKUns.pdf",// link your file
contentType: "application/pdf", //type of file
},
{
filename: "inovices_2.pdf",
path: "https://**************************/invoice/10_9_RMKUns.pdf",
contentType: "application/pdf",
},
];
var nodemailer = require("nodemailer");
var all_transporter = nodemailer.createTransport({
host: process.env.MAIL_SERVICE,
port: 587,
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS,
},
maxConnections: 3,
pool: true,
});
exports.send_email = function (email, subject, html, extra_cc = [], attachments = []) {
return new Promise(async (resolve, reject) => {
var mailOptions = {
from: process.env.MAIL_FROM_ADDRESS,
to: email,
subject: subject,
html: html,
cc: [],
};
mailOptions["cc"] = mailOptions["cc"].concat(extra_cc);
if (attachments.length > 0) mailOptions["attachments"] = attachments;
all_transporter.sendMail(mailOptions, function (error, info) {
// console.log(error);
// console.log(info);
if (error) {
resolve({ failed: true, err: error });
} else {
resolve({ failed: false, data: info.response });
}
});
});
};
The alternative solution is to host your images online using a CDN and link to the online image source in your HTML, eg. <img src="list_image_url_here">.
(I had problems with nodemailer's image embedding using nodemailer version 2.6.0, which is why I figured out this workaround.)
An added benefit of this solution is that you're sending no attachments to nodemailer, so the sending process is more streamlined.
var mailer = require('nodemailer');
mailer.SMTP = {
host: 'host.com',
port:587,
use_authentication: true,
user: 'you#example.com',
pass: 'xxxxxx'
};
Then read a file and send an email :
fs.readFile("./attachment.txt", function (err, data) {
mailer.send_mail({
sender: 'sender#sender.com',
to: 'dest#dest.com',
subject: 'Attachment!',
body: 'mail content...',
attachments: [{'filename': 'attachment.txt', 'content': data}]
}), function(err, success) {
if (err) {
// Handle error
}
}
});
Just look at here. Nodemailer > Message configuration > Attachments
The code snippet is below (pdfkit gets the stream):
// in async func
pdf.end();
const stream = pdf;
const attachments = [{ filename: 'fromFile.pdf', path: './output.pdf',
contentType: 'application/pdf' }, { filename: 'fromStream.pdf', content: stream, contentType: 'application/pdf' }];
await sendMail('"Sender" <sender#test.com>', 'reciver#test.com', 'Test Send Files', '<h1>Hello</h1>', attachments);
Stream uses content not streamSource This bothered me before, share with everyone :)
Reference = https://nodemailer.com/message/attachments/
var mailOption = {
from: from,
to: to,
subject: subject,
text: text,
html: html,
attachments: [
{
filename: filename,
path: filePath
},
]
}

Resources