I am experiencing an unexpected behaviour from nodemailer:
here is my code:
let transporter = nodemailer.createTransport({
host: 'outlook.office365.com',
auth: {
user: process.env.MAIL_USER, // generated ethereal user
pass: process.env.MAIL_PASS, // generated ethereal password
},
tls: {
rejectUnauthorized: false
}});
let info = transporter.sendMail({
from: '"Mark 👻"mymail#outlook.com',
to: "anothermailOfMine#gmail.com",
subject: "Hello ✔",
text: "Hello world?",
html: `<b>
<a href='http://localhost:3000/activate_user/${result._id}'>
<button>Activate
profile</button></a>
</b>`, // html body
});
transporter.sendMail(info, function (err, info) {
if (err) {
console.log(err);
res.json(err);
} else {
console.log(' mail sent');
res.json({success:true, message:''});
}})};
The sendMail method returns an error even if the mail is actually sent successfully, which means that the front-end never receives a positive response about the sending, that's the error i just mentioned:
Error: No recipients defined
at SMTPConnection._formatError
I wonder if I am doing something wrong.
I did find out what the problem was eventually:
the send mail method needed to be called in an asynchronous function.
Related
I was trying to send a test email using SMTP on node mailer but it says connection timed out. the snippet I was using is down below.
const nodemailer = require("nodemailer");
async function main() {
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
pool:true,
host: '213.55.96.132',
port: 25,
auth: {
user: "user#ethionet.et",
pass: "drafgthsjaid321##"
},
pool: true,
logger :true,
debug:true,
secure: false,
})
transporter.verify(function(error, success) {
if (error) {
console.log(error);
} else {
console.log('Server is ready to take our messages');
}
});
let mailOptions = {
from: "user#ethionet.et",
to: ["someemail#gmail.com",],
subject: 'Test email',
text: `Hello world`
};
transporter.sendMail(mailOptions, function(err, data) {
if (err) {
console.log("Error " + err);
} else {
console.log("Email sent successfully");
}
});
}
main().catch(console.error);
I don't mind leaking the credentials and it works when i try and send emails through SMTP from here.
why is this faliing?
You need to read a little more than the first page of documentation :)
Create your message
let message = {
...,
from: 'mailer#nodemailer.com', // listed in rfc822 message header
to: 'daemon#nodemailer.com', // listed in rfc822 message header
envelope: {
from: 'Daemon <deamon#nodemailer.com>', // used as MAIL FROM: address for SMTP
to: 'mailer#nodemailer.com, Mailer <mailer2#nodemailer.com>' // used as RCPT TO: address for SMTP
}
}
Send the message through the transporter
transporter.sendMail(...).then(info=>{
console.log('Preview URL: ' + nodemailer.getTestMessageUrl(info));
});
Turns out the problem was that my ISP blocks port 25.
The full error is EXTREMELY long, but here is a snippet:
TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Object
at PassThrough.Writable.write (_stream_writable.js:289:13)
at PassThrough.Writable.end (_stream_writable.js:583:10)
at Immediate._onImmediate (C:\Users\small\desktop\career-change\coding-round-2\portfolio-round1\recipe-app\projectv2\node_modules\nodemailer\lib
\mime-node\index.js:969:46)
at processImmediate (internal/timers.js:456:21) {
code: 'ERR_INVALID_ARG_TYPE'
}
This is my first time using nodemailer, or any emailing service for that matter. I originally started using it with my personal gmail account, then was getting the issue where gmail was blocking it because it was considered a less secure app. So I changed my email settings to allow access from less secure apps. And then I began getting this error.
I also tried using https://ethereal.email/ to autogenerate an email test account so that I could avoid using gmail, just in case that was the issue.
Here is my nodemailer code:
const express = require("express");
const router = express.Router();
const bodyParser = require("body-parser");
const nodemailer = require("nodemailer");
router.post("/contact", (req, res) => {
const output = {
msg: `You have a new contact request from ${req.body.name}`,
userEmail: req.body.userEmail,
subject: req.body.subject,
message: req.body.message,
};
console.log(res);
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "smtp.ethereal.email",
port: 587,
auth: {
user: "ida.pollich73#ethereal.email",
pass: "JPtPvputy6n8JBzYe2",
},
});
let mailOptions = {
from: '"Nodemailer Contact" <mypersonalaccount#gmail.com>', // sender address
to: "differentpersonalaccount#gmail.com", // list of receivers
subject: "Node Contact Request", // Subject line
text: output, // plain text body
html: output, // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
} else {
console.log(info);
}
res.send("email sent");
console.log("Message sent: %s", info.messageId);
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321#example.com>
// Preview only available when sending through an Ethereal account
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});
});
module.exports = router;
Does anybody have any idea what the error means? Let me know if you need any more info.
In my case, i was a trying to send a wrong data type, so i convert the property html to string and was solved. How i was using next.js, the compiler has reading my html like a JSX element.
const mailOptions= {
from: email,
to: 'mail#gmail.com',
subject: `FORMULARIO DE: ${req.body.name}`,
text: req.body.message,
html: `<div>${req.body.message}</div>`,
}
i think the problem is the return. you must JSON.stringify(error) and get error from sendMail!
If you get some error like this:
TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer. Received an instance of Object
at validChunk (_stream_writable.js:281:10)
at PassThrough.Writable.write (_stream_writable.js:316:21)
at PassThrough.Writable.end (_stream_writable.js:585:10)
at Immediate._onImmediate (/home/ajwebmaker/lsoftweb/node_modules/nodemailer/lib/mime-node/index.js:977:46)
at processImmediate (internal/timers.js:461:21) {
code: 'ESTREAM',
command: 'API'
}
You should add the following line like this:
<div>Name:${req.body.message}</div>
<div>Email${req.body.message}</div>
Add the HTML multiple time as you need to send messages to email.
the result looks like this:
const mailOptions= {
from: email,
to: 'mail#gmail.com',
subject: `FORMULARIO DE: ${req.body.name}`,
text: req.body.message,
html: `<div>Name:${req.body.message}</div><div>Email${req.body.message}</div>`
}
I'm using express to send email by nodemailer module.
my code is following:
app.post('/', (req, res) => {
const output = `
<p>You have new one contact request</p>
<h3>Contact Details</h3>
<ul>
<li>Name:${req.body.name}</li>
<li>Email:${req.body.email}</li>
</ul>
<h3>Message</h3>
<p>${req.body.message}</p>
`;
// create reusable transporter object using the default SMTP transport
let transporter = nodeMailer.createTransport({
host: "mail.gmail.com",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: 'mymail#gamil.com', // generated ethereal user
pass: '2020' // generated ethereal password
},
tls: {
rejectUnauthorized: false
}
});
// send mail with defined transport object
let mailOptions = {
from: "mymail#gamil.com", // sender address
to: "myfriend#gmail.com", // list of receivers
subject: "the subject", // Subject line
html: output // html body
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
// , info.res
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", nodeMailer.getTestMessageUrl(info));
res.render('index', { msg: 'email has been sent' });
res.redirect('back');
});});
after clicking submit button, below code redirects to the Contact page:
res.redirect('back');
and then shows a message by this code:
res.render('index', { msg: 'email has been sent' });
now my aim is to instead of showing text by the forementioned code, showing the text in an alert box.
what I've tried for is like:
res.render('index','<script>alert("email has been sent")</script>');
but this doesn't work at all. by the way I'm not using ajax. then any idea or solution please?
Running a script directly from a server response like <script>doSomethingMaybeBad();</script> will not likely run in modern browsers as it could be used as an attack. At a glance anyway it doesn't seem like you're loading the full page <html>...</html> on the client side with these requests.
I recommend listening to ajax responses from the client side and showing an alert then. Without seeing all your code, here's a rough idea:
Replace:
res.render('index','<script>alert("email has been sent")</script>');
with a JSON response, or response in the same format as you had it before like this:
{ msg: 'email has been sent', status: 200 }
Then in your client code, replace something like this (just guessing what you have as you didn't post a client side example):
$('msg').html(response.msg)
With:
if (response.status === 200) {
alert(msg.msg);
// consider redirecting here if needed?
} else {
// show error, jQuery in this example however may be different for your current
$('msg').html(response.msg)
}
I know there are many posts like this here, but I couldn't find any information that would solve my issue. So I tried using both nodemailer and emailjs.
I have this code:
This is for nodemailer
var nodemailer = require('nodemailer');
nodemailer.createTestAccount((err, account) => {
if (err) console.log(err);
// create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport({
host: "smtp.Hotmail.com", // Just Hotmail doesn't work either
// port: 587,
auth: {
user: 'xxx#outlook.com',
pass: 'xxx'
}
});
// setup email data with unicode symbols
let mailOptions = {
from: `${req.body.fullName} ${req.body.email}`, // sender address
to: 'alexander.ironside#mygeorgian.ca', // list of receivers
subject: 'Email from SMWDB contact form', // Subject line
html: `<h4>Name: ${req.body.fullName}</h4>
<h4>Company: ${req.body.company}</h4>
<h4>Phone: ${req.body.phone}</h4>
<p>Message: ${req.body.message}</p>`
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
// Preview only available when sending through an Ethereal account
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321#example.com>
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});
});
And this for emailjs
var email = require("emailjs");
var server = email.server.connect({
user: "xxx#outlook.com",
password: "xxx",
host: "smtp-mail.outlook.com",
tls: {ciphers: "SSLv3"}
});
var message = {
text: `Test`,
from: `${req.body.fullName} <${req.body.email}>`,
to: `Alex <alexander.ironside#mygeorgian.ca>`, // list of receivers
// cc: "else <else#your-email.com>",
subject: 'Email from SMWDB contact form', // Subject line
attachment:
[
{
data: `
<h4>Name: ${req.body.fullName}</h4>
<h4>Company: ${req.body.company}</h4>
<h4>Phone: ${req.body.phone}</h4>
<p>Message: ${req.body.message}</p>`
, alternative: true
},
]
};
// send the message and get a callback with an error or details of the message that was sent
server.send(message, (err, message) => {
console.log(err || message);
});
The problem I think is that as host both docs say something like this: smtp.your-email.com, meanwhile all code examples say this: host: "Hotmail". What's the correct way?
I don't really care which package I'm using.
I have to use Hotmail/Yahoo and cannot use Gmail (Too many accounts activated with one phone number)
Now to the errors:
Emailjs throws this:
{ Error: bad response on command '
.': 5.2.0 STOREDRV.Submission.Exception:SendAsDeniedException.MapiExceptionSendAsDenied; Failed to process message due to a permanent exception with message Cannot submit message. and then there is a lot of numbers and a callback trace.
Nodemailer throws this:
{ Error: getaddrinfo ENOTFOUND smtp.Hotmail.com smtp.Hotmail.com:587
at errnoException (dns.js:50:10)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26)
code: 'ECONNECTION',
errno: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'smtp.Hotmail.com',
host: 'smtp.Hotmail.com',
port: 587,
command: 'CONN' }
I used to do this in PHP and have no idea why it's so complicated with Node, but I guess there must be a reason.
I asked a friend to create a Gmail account and it worked right away. If you hit the same problem, don't bother with anything else. Just use Google.
That's the transporter code that worked for me
var transporter = nodemailer.createTransport({
host: "smtp.gmail.com", // hostname
auth: {
user: 'xxx#gmail.com',
pass: 'xxx'
}
});
I know how to send mail using nodemailer but I am using email credentials of that, but I don't want to use that. Is there any other method of sending mails.
My nodemailer code snippet is
var nodemailer = require('nodemailer');
// Not the movie transporter!
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'vikaskohli#email.com', // Your email id
pass: 'password' // Your password
}
});
module.exports =
{
sendEmail: function sendMail(varhtml,vartext, varsubject,varfrom, varfrom_name,varto, varto_name, reply_to_email ) {
//setup e-mail data with unicode symbols
var mailOptions = {
from: varfrom_name, // sender address
// to: ['vikaskohli#email.com','vikaskohli1#email.com'], // list of receivers
// to: ['vikaskohli#email.com,vikaskohli1#email.com'], // list of receivers
// to: 'vikaskohli#email.com','vikaskohli1#email.com', // list of receivers
to: varto, // list of receivers
subject: varsubject, // Subject line
text: vartext, // plaintext body
html: varhtml // html body
};
console.log(mailOptions);
// send mail with defined transport object
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
return console.log(error);
}else{
return console.log(info);
}
});
}
}
In the above code, also I don't change my sender name. If I want to send from other mail like
vikaskohli3#gmail.com
but it automatically send from that mail for which I have use credentials here
vikaskohli#email.com
Also I tried using sendmail npm, they don't need any credentials but it send mail in the spam folder
My sendmail code snippet
var sendmail = require('sendmail')({silent: true})
sendmail({
from: 'vikaskohli#email.com',
to: 'vikaskohli#email.com,vikaskohli1#email.com',
subject: varsubject, // Subject line
html: varhtml,
attachments: [
]
}, function (err, reply) {
console.log(err && err.stack)
console.dir(reply)
});
I use sendmail like your bottom code, and it works fine for me. Perhaps the reason it's going to spam is because your settings in the email provider. Most likely the email you chose as sender (#email.com) seems like a spam to that service provider or your settings.