I have a Namecheap PrivateEmail.com account that I am trying to use to send verification codes to my users upon signup. I am trying to test the send email function using a small integration test.
I can confirm that the email account itself can send and receive emails. I confirmed by sending and receiving an email.
I have a collection of research I've been using:
BLOG: How to send a magic link with Nodemailer and Namecheap
https://nodemailer.com/smtp/ <= docs
StackOverflow: Send Nodemailer e-mail with Namecheap email
My code is as follows
// in a test file
const connectionEstablished = await verifySMTPConnection();
expect(connectionEstablished).toBe(true);
const myEmail = process.env.MY_EMAIL ? process.env.MY_EMAIL : "fail";
const senderEmail = process.env.PRIVATE_EMAIL;
expect(senderEmail).toBeDefined();
if (myEmail == "fail") {
throw Error("fail to load email from env");
}
const payload = { from: senderEmail, to: myEmail, subject: "Test email!", html: "foo!" };
sendEmail(payload);
console.warn("You just sent a real email"); // this logs!
expect(true).toBe(false); // intentional failure to highlight that the test has run.
Here are my functions
async function sendEmail({ to, subject, html, from = config.emailFrom }: ISendEmail) {
const transporter = nodemailer.createTransport({
host: config.emailHost,
port: config.emailPort,
auth: { user: config.emailUser, pass: config.emailPassword },
});
console.log("Sending email to", to);
console.warn("Email might be enabled");
await transporter.sendMail({ from, to, subject, html });
}
export function verifySMTPConnection(): Promise<boolean> {
const transporter = nodemailer.createTransport({
host: config.emailHost,
port: config.emailPort,
auth: { user: config.emailUser, pass: config.emailPassword },
});
return new Promise((resolve, reject) => {
transporter.verify(function (error, success) {
if (error) {
console.log(error);
resolve(false);
} else {
console.log("Server is ready to take our messages");
resolve(true); // I get the "true" response every time
}
});
});
}
export default sendEmail;
And the code for the config:
const emailFrom = process.env.PRIVATE_EMAIL ? process.env.PRIVATE_EMAIL : failure;
const emailHost = process.env.PRIVATE_EMAIL_HOST ? process.env.PRIVATE_EMAIL_HOST : failure;
const emailPort = process.env.PRIVATE_EMAIL_PORT ? parseInt(process.env.PRIVATE_EMAIL_PORT, 10) : 465;
const emailUser = process.env.PRIVATE_EMAIL_USER ? process.env.PRIVATE_EMAIL_USER : failure;
const emailPassword = process.env.PRIVATE_EMAIL_PASSWORD ? process.env.PRIVATE_EMAIL_PASSWORD : failure;
if (emailFrom == failure || emailHost == failure || emailUser == failure || emailPassword == failure) {
throw Error("Failed to load private email details");
}
export default { emailFrom, emailHost, emailPort, emailUser, emailPassword };
I can confirm that:
- my PRIVATE_EMAIL field really is my desired email account
PRIVATE_EMAIL_HOST=mail.privateemail.com
is correct as per this postPRIVATE_EMAIL_PORT=465
is correct as per here on freecodecamp (I tried587
as well)PRIVATE_EMAIL_USER
andPRIVATE_EMAIL_PASSWORD
are both correct.
changing the password to be incorrect gives the error: Error: Invalid login: 535 5.7.8 Error: authentication failed:
which leads me to believe that since resolve(true);
occurs when I have the correct pw, I have the correct credentials and the connection is established. The docs say "Be aware though that this call only tests connection and authentication but it does not check if the service allows you to use a specific envelope From address or not" but that seems irrelevant.
Could there be something in PrivateEmail settings I am missing?