I'm setting up a website with a node.js backend in firebase. One of the pages is a contact page where the user submits the form and its contents get sent to my email address.
I set everything up with mailgun, using the mailgun api.
const functions = require("firebase-functions");
const express = require('express');
const mailgun = require('mailgun-js');
const app = express();
app.use(express.urlencoded());
app.use(express.json());
app.use(express.static('public'));
function sendMsg(name, email, subject, message) {
const mg = mailgun({
apiKey: 'APIKEY',
domain: 'sandboxrandomnumbers.mailgun.org'
});
const data = {
from: `${name} <${email}>`,
to: 'myemail',
subject: subject,
text: message
};
mg.messages().send(data, (err, body) => {
console.log(body);
})
}
app.post('/contact/success', (req, res) => {
let name = req.body.name;
let email = req.body.email;
let subject = req.body.subject;
let message = req.body.message;
sendMsg(name, email, subject, message);
res.redirect('/contact/success');
})
exports.website = functions.https.onRequest(app);
What's happening is the messages are being queued but not sent (based on what is printed on the console). How do I make sure that the messages are sent immediately and not queued?
PS: I'm still a beginner so please bear with me.
You should check the spam folder of your mail account. That's where those mails usually end up.
Also if you want to see the status of you mails, go to the "sending" menu in the side navbar.
There you can see the status of your mails like - Name Accepted, Delivered, Bounced, Opened, Clicked, Complained, etc.
Check out this image -
Related
I am trying to get the contact list and check if the email recipient opened the email or not.
I found this code and tried but got 401.
import config from "#server/config"
sgClient.setApiKey(config.sendgridKey)
const headers = {
"on-behalf-of": "my account user name" // I put my account user name here
}
const request = {
url: `/v3/subusers`,
method: "GET"
} as any
const list = await sgClient
.request(request)
.then()
.catch((err) => {
console.log("list", err.response.body)
})
What do I need to put for the header 'on-behalf-of'? What does the subuser's user name?
And is there any example to get the 'email opened' event?
I am using Node.js.
Thank you!
Twilio SendGrid developer evangelist here.
The API you are trying to use there is the subuser API, not the contacts API. The subuser API is for managing subusers, which are accounts you can apply credit to and send emails from. Subusers are only available on Pro or Premier email accounts or Advanced Marketing Campaign accounts.
However, even if you were to use the Contacts API to get a list of your contacts, that's not the way to see if they have opened an email.
You should instead register for the Event Webhook. With the Event Webhook, SendGrid will send you webhook requests about events that occur as SendGrid processes your emails. These events include "processed", "delivered", "opened", and "clicked" and there are more in the documentation.
To handle the Event Webhook you need to create yourself an endpoint that can receive incoming HTTP requests. Here is an example from the documentation using Express.
const express = require('express');
const app = express();
app.use(express.json());
app.configure(function(){
app.set('port', process.env.PORT || 3000);
});
app.post('/event', function (req, res) {
const events = req.body;
events.forEach(function (event) {
// Here, you now have each event and can process them how you like
processEvent(event);
});
});
var server = app.listen(app.get('port'), function() {
console.log('Listening on port %d', server.address().port);
});
I have been creating the system for several hours. I almost put the project into an end, but somehow I cannot receive any emails after filling the form. Does anyone know what is the cause of this problem ??
First, I installed node.js, then nodemon. I have four main files and a folder in the project folder - app.js, package-lock.json, contact.handlebars, package.json and node_module.
the code below is app.js
const express = require("express");
const bodyParser = require("body-parser");
const exphbs = require("express-handlebars");
const path = require("path");
const nodemailer = require("nodemailer");
const app = express();
// view engine setup
app.engine("handlebars", exphbs());
app.set("view engine", "handlebars");
// Static folder
app.use("/public", express.static(path.join(__dirname, "public")));
// Body Parser Middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get("/", (req, res) => {
res.render("contact", { layout: false });
});
app.post("/send", (req, res) => {
const output = `
<p>You have a new contact request</p>
<h3>Contact Details</h3>
<ul>
<li>Name: ${req.body.name}</li>
<li>Company: ${req.body.company}</li>
<li>Email: ${req.body.email}</li>
<li>Phone: ${req.body.phone}</li>
</ul>
<h3>Message</h3>
<p>${req.body.message}</p>
`;
async function main() {
// Generate test SMTP service account from ethereal.email
// Only needed if you don't have a real mail account for testing
let testAccount = await nodemailer.createTestAccount();
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "I PUT 1ST SERVERNAME HERE OF HOSTGATOR",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: "MY 1ST EMAIL ACCOUNT", // generated ethereal user
pass: "********" // generated ethereal password
},
tls: {
rejectUnauthorized: false
}
});
// send mail with defined transport object
let info = await transporter.sendMail({
from: '"Nodemailer Contact" <MY 1ST EMAIL ACCOUNT>', // sender address
to: "MY SECOND EMAIL ACCOUNT", // list of receivers
subject: "Node Contact Request", // Subject line
text: "Hello world?", // plain text body
html: output // html body
});
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
res.render("contact", { layout: false }, { msg: "Email has been sent" });
}
main().catch(console.error);
});
app.listen(3000, () => console.log("server started..."));
Ethereal's test SMTP service doesn't send the emails. From their website:
It's a completely free anti-transactional email service where messages never get delivered.
It looks like it lets you view a preview of the sent mail to check your application is working correctly, but to actually send email you need to set up a real SMTP server. You can get SMTP credentials for sending transactional mail from applications from various companies such as SendGrid and Mailgun.
I have mailgun setup in my node.js using nodemailer and I cannot get it to send emails when I test my route using my REST client. When I directly write the code into the server file, the email sends right away when the server starts.
However, when I write the email api in an app.post and test it with a REST client the email fails on the mailgun side and gets rejected by google??? This is only my assumption because of the error code I am getting.
Server response: 550 5.7.1 Unauthenticated email from guest.com is not
accepted due to domain's 5.7.1 DMARC policy. Please contact the administrator
of guest.com domain if 5.7.1 this was a legitimate mail. Please visit 5.7.1
https://support.google.com/mail/answer/2451690 to learn about the 5.7.1 DMARC
initiative. s12-v6si3013316qtg.362 - gsmtp
I've followed the link provided and the documentation says to check with the domain server. I do not understand why I am getting this error because I already authenticated my gmail within mailgun.
I've also tried switching to directly using the mailgun-js middleware. Found three different mailgun-js api from mailgun.com, mailgun-js on github, and mailgun-js on npmjs.com. Got the same error as above.
At a loss. Don't know what to do.
My nodemailer code:
const express = require('express');
const nodemailer = require('nodemailer');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();
const port = 3000;
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'dist')));
app.post('/email', (req, res) => {
let transporter = nodemailer.createTransport({
host: 'smtp.mailgun.org',
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: 'postmaster#sandboxc8f2ecf64f364ca6ad740e658485c557.mailgun.org',
pass: 'my API key here'
},
tls: {
rejectUnauthorized: false
}
});
// setup email data with unicode symbols
let mailOptions = {
from: req.body.from, // sender address
to: 'cu0ngpitt#gmail.com', // list of receivers
subject: 'Someone wrote you from your Online Resume!', // Subject line
text: req.body.messge, // plain text body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
});
});
app.get('/', (req, res) => {
res.send('Hello world');
});
app.listen(port, () => {
console.log('Server running on port ' + port);
})
Mailgun responded to my ticket and said due to DMARC security, I am only allowed to send an email with the same domain as my mailgun account.
Since I had a free mailgun account. I had to change my sender address to my free mailgun address, which was postmaster#sandbox"some long string".mailgun.org
If using nodemailer, you can leave off the sender email or hard code it in.
If using mailgun-js, you have to hard code it in.
My old code:
// setup email data with unicode symbols
let mailOptions = {
from: req.body.from, // sender address
to: 'cu0ngpitt#gmail.com', // list of receivers
subject: 'Someone wrote you from your Online Resume!', // Subject line
text: req.body.messge, // plain text body
};
Corrected code:
// setup email data with unicode symbols
let mailOptions = {
postmaster#sandbox"some long string".mailgun.org, // sender address
to: 'cu0ngpitt#gmail.com', // list of receivers
subject: 'Someone wrote you from your Online Resume!', // Subject line
text: req.body.messge, // plain text body
};
I think I'm missing something very simple here. I have a simple, one page node.js app that uses nodemailer to email any form data to my inbox.
My index.js file:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var nodemailer = require('nodemailer');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'myemail#gmail.com',
pass: 'mypassword'
}
});
app.use(express.static('public')); //public folder with my html files
app.get('', function (req, res) {
res.sendFile(__dirname + "/");
})
app.post('/', function (req, res) {
response = {
name: req.body.name,
email: req.body.email,
message: req.body.message
};
var mailClient = {
from: 'myemail#gmail.com',
to: 'myemail#gmail.com',
subject: `Message from ${response.name}`,
text: 'MyMessage'
};
transporter.sendMail(mailClient, function (error, info) {
if (error) {
console.log(error); //not happening
} else {
res.redirect("/success.html"); //also not happening
}
});
})
var server = app.listen(80, function () {
var host = server.address().address
var port = server.address().port
console.log("App listening at http://%s:%s", host, port)
})
When I run this on my local machine using npm start in the root directory, the app runs perfectly fine on localhost. Nodemailer works properly; when I submit, my form data gets emailed to myself and I get redirected to my success page.
However, when I deploy this to Firebase, it seems the nodemailer part doesn't work. The page loads in with my static files, but when I try to submit anything via the form, the page simply refreshes (like when you have a submit button with bare html), instead of redirecting me to my success page and emailing data.
Is there something I need to change in my code to make it work with firebase?
Edit - no logs:
Google requires a paid account in order to make use of "Outbound Networking". The Free Tier does not allow you to make outbound calls. This would include sending mail to a remote mail server (like sending an email to a Yahoo, Gmail, or Outlook account).
See their pricing page for more info.
Look for "Outbound Networking".
If you'd like to leverage Gmail's API, you should still be able to use nodemailer with firebase functions and achieve what you're looking for and remain on the Free Tier. A fully working example is already available in the firebase-samples repository! I would like to highlight what the linked tutorial mentions, which is that Gmail does have an email sending quota that you should be aware of.
I tried to figure out problem in your code but didn't found any, I also have functionality to send email with verification code for authenticate/verify email id. For that I create one gmail id and gave that id/password for sending mail. Mails are sent from that gmail id with node.js when ever user register is email id we send email with veirfication code. My code is as under:
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');
var bodyParser = require('body-parser');
var users = require('./users/route');
const app = express();
const nodemailer = require('nodemailer');
// Configure the email transport using the default SMTP transport and a GMail account.
// For other types of transports such as Sendgrid see https://nodemailer.com/transports/
// TODO: Configure the `gmail.email` and `gmail.password` Google Cloud environment variables.
const gmailEmail = 'myapp#gmail.com';
const gmailPassword = 'password';
const gcm = require('node-gcm');
const mailTransport = nodemailer.createTransport(
`smtps://${gmailEmail}:${gmailPassword}#smtp.gmail.com`);
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://myapp.firebaseio.com"
});
//admin.initializeApp(functions.config().firebase);
// Express middleware that validates Firebase ID Tokens passed in the Authorization HTTP header.
// The Firebase ID token needs to be passed as a Bearer token in the Authorization HTTP header like this:
// `Authorization: Bearer <Firebase ID Token>`.
// when decoded successfully, the ID Token content will be added as `req.user`.
const authenticate = (req, res, next) => {
if (!req.headers.authorization || !req.headers.authorization.startsWith('Bearer')) {
res.status(403).send('Unauthorized');
return;
}
const idToken = req.headers.authorization.split('Bearer ')[1];
admin.auth().verifyIdToken(idToken).then(decodedIdToken => {
req.user = decodedIdToken;
next();
}).catch(error => {
res.status(403).send('Unauthorized');
});
};
app.get("/token", (req, res) => {
res.status(200).send(admin.auth().applicationDefault());
admin.auth().createCustomToken(req.query.uid)
.then(function (customToken) {
res.status(200).send(customToken);
})
.catch(function (error) {
console.log("Error creating custom token:", error);
});
});
// GET /api/verifyEmail?code="1234"
app.get('/verifyEmail', (req, res) => {
// Get the one-time code from the query parameter.
var verificationCode = req.query.code;
var displayName = req.query.displayName;
var email = req.query.email; //If GET request
const mailOptions = {
from: `Linkuni <noreply#firebase.com>`,
to: email
};
// The user subscribed to the newsletter.
mailOptions.subject = `Welcome to Linkuni`;
mailOptions.text = `Hi ${displayName || ''}\n\n Welcome to Linkuni. We hope you will enjoy our service. Please enter this code:${verificationCode} into the app.\n\nThank you,\nLinkuni Team`;
return mailTransport.sendMail(mailOptions).then(() => {
console.log('Verification email sent to:', email);
});
});
Hope this helps!! :)
How to collect data from form (name, email, attachments) and submit them to my email using express. I didn't find a comprehensive articles on this topic. I will be grateful for the help.
I am considering you know how to submit form
To send any mail through node install popular module 'nodemailer'
1-install nodemailer module in your project directory
npm install nodemailer
2-come to the controller where you are handling form submit data on server
var express = require('express'),
nodemailer = require("nodemailer");
app = express.createServer();
app.use(express.bodyParser());
app.post('/formProcess', function (req, res) {
var data=req.body;
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
auth: {
user: "email#gmail.com",
pass: "gmailPassword"
}});
smtpTransport.sendMail({ //email options
from: "Sender Name <email#gmail.com>",
to: "Receiver Name <receiver#email.com>", // receiver
subject: "Emailing with nodemailer", // subject
html: "here your data goes" // body (var data which we've declared)
}, function(error, response){ //callback
if(error){
console.log(error);
}else{
console.log("Message sent: " + res.message);
}
smtpTransport.close();
}); });