What I want to achieve
I want to send an email using email-templates and configuring the transport to use sendgrid in My
Node/Express backend
However when I send my email, I get no errors in the console but I do not receive any emails on my email client. and I have made extra sure all my information with API Keys and Email addresses are correct.
Code
const express = require('express');
const nodemailer = require("nodemailer")
const sendgridTransport = require("nodemailer-sendgrid-transport")
const router = express.Router();
let transporter = nodemailer.createTransport(
sendgridTransport({
auth: {
api_key:
process.env.SENDGRID_API_KEY
}
})
);
const Email = require('email-templates');
const path = require('path')
router.post('/email', (req,res) => {
const email = new Email({
message: {
from: 'info#4loop.online'
},
transport: {
jsonTransport: transporter
}
});
email
.send({
template: path.join(__dirname, "../templates", "contact"),
message: {
to: 'info#4loop.online'
},
locals: {
name: 'Elon'
}
})
.then(console.log)
.catch(console.error);
})
module.exports = router
link to email-template docs
https://www.npmjs.com/package/email-templates
Response
{
envelope: { from: 'info#4loop.online', to: [ 'info#4loop.online' ] },
messageId: '<1082af04-68ec-2337-1fa0-926aca91b9ce#4loop.online>',
message: '{"to":[{"address":"info#4loop.online","name":""}],"from":{"address":"info#4loop.online","name":""},"attachments":[],"subject":"Hi Elon, welcome to Mars","html":"\\n<p>Hi Elon,</p>\\n<p>Welcome to Mars, the red planet.</p>","text":"<hey>There.</hey>","headers":{},"messageId":"<1082af04-68ec-2337-1fa0-926aca91b9ce#4loop.online>"}',
originalMessage: {
to: 'info#4loop.online',
from: 'info#4loop.online',
attachments: [],
subject: 'Hi Elon, welcome to Mars',
html: '\n<p>Hi Elon,</p>\n<p>Welcome to Mars, the red planet.</p>',
text: '<hey>There.</hey>'
}
}
{
envelope: { from: 'info#4loop.online', to: [ 'info#4loop.online' ] },
messageId: '<0e80bb1f-01ae-d994-ea06-549e34a0eed0#4loop.online>',
message: '{"to":[{"address":"info#4loop.online","name":""}],"from":{"address":"info#4loop.online","name":""},"attachments":[],"subject":"Hi Elon, welcome to Mars","html":"\\n<p>Hi Elon,</p>\\n<p>Welcome to Mars, the red planet.</p>","text":"<hey>There.</hey>","headers":{},"messageId":"<0e80bb1f-01ae-d994-ea06-549e34a0eed0#4loop.online>"}',
Answer
The answer was really simple. all you need to do is replace the transport configuration with this.
const email = new Email({
message: {
from: 'info#4loop.online'
},
send: true,
transport:transporter
});
Related
i new to mail-gun i'm trying to send an email after successful payment, but each time the payment is cofirmed , i don't get an email
this how i use it
const domain = 'https://app.mailgun.com/app/sending/domains/sandbox18d7fe3d7f4c6baf525.mailgun.org ';
var mailgun = require('mailgun-js')({
apiKey: "MY_APIKEY",
domain: domain
});
this is my email template
stripe.charges
.create(newCharge, function(err, charge) {
// send response
if (err) {
console.error(err);
res.json({ error: err, charge: false });
} else {
var emailTemplate = `Hello ${newCharge.shipping.name}, \n
Amount: ${newCharge.amount} \n
Thank you!`;
// compose email
var emailData = {
from: "no-reply#YOUR-DOMAIN.com",
to: req.body.email,
subject: "Bundle of Sticks Receipt - " + charge.id,
text: emailTemplate
};
// send email to customer
mailgun.messages().send(emailData);
emailData["to"] = "your_support_email#gmail.com";
emailData["subject"] = `New Order: Bundle of Sticks - ${charge.id}`;
// send email to supplier
mailgun.messages().send(emailData);
// send response with charge data
res.json({ error: false, charge: charge });
}
})
how can i go about this , the payment is always successful but the email dont go through
You should install nodemailer and nodemailer-mailgun-transport and work with those.
And using those it will work a little something like this:
import * as nodemailer from 'nodemailer';
import * as mailGun from 'nodemailer-mailgun-transport';
const auth = {
api_key: <YOUR_API_KEY>
domain: <YOUR_DOMAIN>,
}
const transporter = nodemailer.createTransport(mailGun(auth));
const mailOptions = {
sender: "John Doe",
from: email,
to: '<WHATEVER_EMEIL>',
subject: '<YOUR_SUBJECT>',
text: '<YOUR_TEXT>',
};
transporter.sendMail(mailOptions);
Just edit those to suit your need and variables, but that's generally the approach.
Last week I initially posted this asking for help using nodemailer and googleapi. I'm trying to use nodemailer and googleapis to send an email. I have set up my project in https://console.cloud.google.com/ and have set my CLIENT_ID, CLIENT_SECRET, CLIENT_REDIRECT_URI and REFRESH_TOKEN in a .env and have confirmed that the values are being populated. In debug mode I have noticed the following error stack when I send the error:
'Error: invalid_grant\n at Gaxios._request (/Users/ENV/Tutoring-Invoice-Management-System/node_modules/gaxios/build/src/gaxios.js:130:23)\n at processTicksAndRejections
(node:internal/process/task_queues:96:5)\n
at async OAuth2Client.refreshTokenNoCache (/Users/ENV/Tutoring-Invoice-Management-System/node_modules/google-auth-library/build/src/auth/oauth2client.js:174:21)\n
at async OAuth2Client.refreshAccessTokenAsync (/Users/ENV/Tutoring-Invoice-Management-System/node_modules/google-auth-library/build/src/auth/oauth2client.js:198:19)\n
at async OAuth2Client.getAccessTokenAsync (/Users/ENV/Tutoring-Invoice-Management-System/node_modules/google-auth-library/build/src/auth/oauth2client.js:227:23)\n
at async sendMail (/Users/ENV/Tutoring-Invoice-Management-System/service/send-email.js:17:29)'
The code is below. I have edited it based on an answer to the question already. My question now is, why am I getting the invalid_grant error? Based on the formal documentation I have set everything up correctly in https://console.cloud.google.com/apis/credentials/oauthclient. But perhaps there is an issue there?
const nodemailer = require('nodemailer');
const { google } = require('googleapis');
require('dotenv').config();
console.log("CLIENT_ID: " + process.env.CLIENT_ID);
console.log("CLIENT_SECRET: " + process.env.CLIENT_SECRET);
console.log("CLIENT_REDIRECT_URI: " + process.env.REDIRECT_URI);
console.log("REFRESH_TOKEN: " + process.env.REFRESH_TOKEN);
const oAuth2Client = new google.auth.OAuth2(process.env.CLIENT_ID, process.env.CLIENT_SECRET, process.env.REDIRECT_URI);
console.log("oAuth2Client: " + oAuth2Client);
oAuth2Client.setCredentials({refresh_token: process.env.REFRESH_TOKEN})
async function sendMail() {
try {
const accessToken = await oAuth2Client.getAccessToken()
const transport = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
type: 'OAuth2'
}
});
const mailOptions = {
from: 'envolonakis#gmail.com',
to: 'envolonakis#gmail.com',
subject: "Test Email API Subject",
text: "Test Email API Text",
html: "<h1> Test Email API HTML </h1>",
auth: {
user: process.env.OWNER_EMAIL,
accessToken: accessToken.token
}
}
const result = await transport.sendMail(mailOptions);
return result;
} catch (error) {
console.log(error.stack);
return error;
}
}
sendMail()
From the official documentation, this is what you need to use:
try {
const accessToken = await oAuth2Client.getAccessToken()
const transport = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
type: 'OAuth2'
}
});
const mailOptions = {
from: process.env.OWNER_EMAIL,
to: process.env.RECIPIENT,
subject: "Test Email API Subject",
text: "Test Email API Text",
html: "<h1> Test Email API HTML </h1>",
auth: {
user: process.env.OWNER_EMAIL,
accessToken: accessToken.token
}
}
const result = await transport.sendMail(mailOptions);
return result;
} catch (error) {
return error;
}
One error that you have whilst using the google api authentication library is with the token. You were passing the complete token object to the auth configuration of nodemailer instead of just the access token string. Another thing to keep in mind, adding or removing parameters to the auth configuration of nodemailer will lead to different errors.
Using #Morfinismo 's solution in addition to creating a new oAuth on https://developers.google.com/oauthplayground resolved my issue.
The following post from Twilio explains how to write and implement a function for sending the link of a recorded message to email.
https://www.twilio.com/blog/forward-voicemail-recordings-to-email
I want to attach to the voicemail recording rather than just send the link. Here is my attempt at modifying their code. Unfortunately it's causing a 500 error. I'm not very experience with NodeJS so perhaps you can help.
Dependencies for SendGrid and FS are included and this function worked perfectly until I modified it with FS, pathToAttachment, attachment variables and the attachments array.
//Initialize SendGrid Mail Client
const sgMail = require('#sendgrid/mail');
//FileSystem
const fs = require("fs");
// Define Handler function required for all Twilio Functions
exports.handler = function(context, event, callback) {
pathToAttachment = `${event.RecordingUrl}`;
attachment = fs.readFileSync(pathToAttachment).toString("base64");
// Build SG mail request
sgMail.setApiKey(context.SENDGRID_API_SECRET);
// Define message params
const msg = {
to: context.TO_EMAIL_ADDRESS,
from: context.FROM_EMAIL_ADDRESS,
fromname: 'Voicemail',
text: `URL is: ${event.RecordingUrl}`,
subject: `${event.From} (${event.country} / ${event.lang})`,
attachments: [
{
content: attachment,
filename: "Voicemail.wav",
disposition: "attachment"
}
]
};
// Send message
sgMail.send(msg)
.then(response => {
console.log("Neat.")
callback();
})
.catch(err => {
console.log("Not neat.")
callback(err);
});
};
This is how you modify the code from the Twilio blog:
Forward Voicemail Recordings to Email w/ Studio, Functions, & SendGrid
https://www.twilio.com/blog/forward-voicemail-recordings-to-email
.. to attach the email recording instead of link to it and how to add a from name as well as a from email address.
const request = require('request');
const sgMail = require('#sendgrid/mail');
exports.handler = function(context, event, callback) {
const fileUrl = event.RecordingUrl;
// Build SG mail request
sgMail.setApiKey(context.SENDGRID_API_SECRET);
request.get({ uri: fileUrl, encoding: null }, (error, response, body) => {
const msg = {
to: context.TO_EMAIL_ADDRESS,
from: {
"email": context.FROM_EMAIL_ADDRESS,
"name": `My company`
},
text: `Attached voicemail from ${event.From}.`,
subject: `${event.From}`,
attachments: [
{
content: body.toString('base64'),
filename: `MyRecording.wav`,
type: response.headers['content-type']
}
]
};
// Send message
sgMail.send(msg)
.then(response => {
console.log("Neat.")
callback();
})
.catch(err => {
console.log("Not neat.")
callback(err);
});
});
};
This is how you modify the code from
I want to send a mail once a user is created with a firebase cloud functions, using nodemail and postmark.
I followed this tutorial : Tutorial link from Dave Martin
But keep getting this error:
There was an error while sending the welcome email: { status: 422, message: 'Zero recipients specified', code: 300 }
Here is my code to send a mail from cloud functions:
//Mail
const nodemailer = require('nodemailer')
const postmarkTransport = require('nodemailer-postmark-transport')
// Google Cloud environment variable used:
// firebase functions:config:set postmark.key="API-KEY-HERE"
const postmarkKey = functions.config().postmark.key
const mailTransport = nodemailer.createTransport(postmarkTransport({
auth: {
apiKey: postmarkKey
}
}))
exports.OnUserCreation = functions.auth.user().onCreate((user) =>
{
console.log("user created: " + user.data.uid);
console.log("user email: " + user.data.email);
sendEmail(user);
})
function sendEmail(user)
{
// Send welcome email to new users
const mailOptions =
{
from: '"test" <test#test.com>',
to: user.email,
subject: 'Welcome!',
html: 'hello'
}
// Process the sending of this email via nodemailer
return mailTransport.sendMail(mailOptions)
.then(() => console.log('Welcome confirmation email sent'))
.catch((error) => console.error('There was an error while sending the welcome email:', error))
}
My postmark.key is already setup in the firebase config... The API tell me the problem is the format I use to send the mail informations.. How could I fix it ?
Update
I also tried to modify the mailOptions as follow and still the same error:
const mailOptions = {
from: 'test#test.com',
to: user.email,
subject: 'Welcome!',
textBody: 'hello'
}
Decided to restart from scratch by following only postmark documentation (wich is really good by the way).
So here are the very simple steps to send mail from events in firebase cloud functions:
1- download packages:
Run: npm install postmark
2- register to postmark
Register to PostMark
- then find your API key.
3- setup firebase environment config:
Run : firebase functions:config:set postmark.key="API-KEY-HERE"
4 index.js code to be added:
//Mail
const postmark = require('postmark')
const postmarkKey = functions.config().postmark.key;
const mailerClient = new postmark.ServerClient(postmarkKey);
exports.OnUserCreation = functions.auth.user().onCreate((user) => {
console.log("user created: " + user.data.uid);
console.log("user email: " + user.data.email);
return sendEmail(user);
})
// Send welcome email to new users
function sendEmail(user) {
const mailOptions = {
"From": "XYZ#YOURDOMAIN.com",
"To": user.data.email,
"Subject": "Test",
"TextBody": "Hello from Postmark!"
}
return mailerClient.sendEmail(mailOptions)
.then(() => console.log('Welcome confirmation email sent'))
.catch((error) => console.error('There was an error while sending the welcome email:', error))
}
That's it.
No need to download nodemailer nor use a transporter.
I have written the code shown below to send the push notification:
const pushpad = require('pushpad');
require('dotenv').config();
const axios = require('axios');
const project = new pushpad.Pushpad({
authToken: process.env.PUSH_PAD_AUTH_TOKEN,
projectId: process.env.PUSH_PAD_PROJECT_ID
});
console.log('called pushpad');
let notification = new pushpad.Notification({
project: project,
body: 'Hello world!',
title: 'Website Name',
targetUrl: 'http://example.com',
iconUrl: 'http://example.com/assets/icon.png',
imageUrl: 'http://example.com/assets/image.png',
ttl: 604800,
requireInteraction: true,
customData: '123',
actions: [
{
title: 'My Button 1',
targetUrl: 'http://example.com/button-link',
icon: 'http://example.com/assets/button-icon.png',
action: 'myActionName'
}
],
starred: true,
sendAt: new Date(Date.UTC(2016, 7 - 1, 25, 10, 9)),
customMetrics: ['examples', 'another_metric']
});
// deliver to everyone
notification.broadcast(function (err, result) {
console.log("error is " + err);
});
module.exports = notification;
but somehow, as soon as I run this code, it gives me error Unprocessable Entity . So how to solve this error ?
Probably you have entered some wrong parameters. For example customMetrics must be defined in your project settings before using them.
Try the same code with a simple notification:
let notification = new pushpad.Notification({
project: project,
body: 'Hello world!'
});