NodeMailer queuing outgoing email, but email never sends - email

I'm trying to send an email from my own domain without using an external SMTP server. I'm using NodeMailer's SMTP connection:
let options = {
secure: true,
port: consts.portOut,//465
host: consts.host, //mydomain.com
transactionLog: true,
debug: true,
requireTLS: true,
authMethod: 'PLAIN',
};
let connection = new SMTPConnection(options);
connection.connect(function() {
let auth = {
user: 'abc',
pass: 'def'
};
connection.login(auth, function(err) {
if (err) {
console.log("Authentication failed!", err);
}
console.log("Authentication to SMTP server successful.");
let envelope = {
from: 'fee#mydomain.com',
to: 'myemail#gmail.com'
};
let message = 'message hello world';
connection.send(envelope, message, function(err, info) {
if (err) {
console.log("err:::", err);
} else {
console.log('info?', info);
//connection.quit();
}
});
connection.quit();
});
});
connection.on("error", function(err) {
console.log(err);
});
My server code using NodeMailer's SMTP Server:
const options = {
secure: true,
size: 25000000, //25MB
authMethods: ['PLAIN'],
key: hskey,
cert: hscert,
ca: [hschain],
onAuth(auth, session, callback) {
if(auth.username !== 'abc' || auth.password !== 'def') {
return callback(new Error('Invalid username or password'));
}
callback(null, {user: 123}); // where 123 is the user id or similar property
},
onConnect(session, callback) {
console.log("the address is:", session.remoteAddress)
if (session.remoteAddress === consts.ip) {
return callback(); // Accept the address
} else {
return callback(new Error('Only connections from %s allowed', consts.ip));
}
},
onData(stream, session, callback) {
simpleParser(stream, (err, parsed) => {
if(err) {
console.error(err);
} else {
console.log(parsed);
}
});
stream.on('end', function () {
let err;
if(stream.sizeExceeded){
err = new Error('Message exceeds fixed maximum message size');
err.responseCode = 552;
return callback(err);
}
callback(null, 'Message queued as abcdef');
});
}
};
const emailServer = new SMTPServer(options);
emailServer.listen(consts.portOut, function () {
processSMTPConnection(consts, hskey);
});
emailServer.on("error", function (err) {
console.error("Error %s", err.message);
});
So after my client connects to my local SMTP server, the last message I get is 'Message queued as abcdef' and nothing ever sends (nothing ever arrives in my gmail inbox or any other email testing services)...
No incorrect ports are blocked, so I must be missing something(?).
Is this not how to correctly use NodeMailer?
Should I be able to send emails from my local domain using NodeMailer?

Documentation here has a note that states:
This module does not make any email deliveries by itself. smtp-server
allows you to listen on ports 25/24/465/587 etc. using SMTP or LMTP
protocol and that’s it. Your own application is responsible of
accepting and delivering the message to destination.
(emphasis mine)
Your server seems to accept the email (that's why it's showing that the message has been queued) but it doesn't delivers to destination.
To expand a little bit on how to send the message once it arrives to your SMTP server. If the TO address is local, just put the message in their mailbox. But if you want to "remail" the message, you need to contact the TO mail exchange with the message.
Something like:
const toExchange = getMX(parsed.to);
const outMessage = createMessageFromParsed(parsed);
const transporter = createTransport({
port: 25,
host: toExchange,
name: os.hostname(),
});
transporter.sendMail(outMessage);

Related

Unable to receive mail sent via sendgrid

I'm creating a contact form using Nextjs and SendGrid, according to this header status
202
{
server: 'nginx',
date: 'Thu, 08 Dec 2022 16:29:25 GMT',
'content-length': '0',
connection: 'close',
'x-message-id': 'CaVdpVAURza6JrUF7yIQQA',
'access-control-allow-origin': 'https://sendgrid.api-docs.io',
'access-control-allow-methods': 'POST',
'access-control-allow-headers': 'Authorization, Content-Type, On-behalf-
of, x-sg-elas-acl',
'access-control-max-age': '600',
'x-no-cors-reason':
'https://sendgrid.com/docs/Classroom/Basics/API/cors.html',
'strict-transport-security': 'max-age=600; includeSubDomains'
}
the email is sent but I find nothing in my inbox,
and this error occurs in the terminal
API resolved without sending a response for /api/contact, this may result in stalled requests.
I don't know what mistake I've done but. I invite you to look at my code bellow:
API :
import sgMail from "#sendgrid/mail";
export default function handler(req, res) {
if (req.method !== "POST") {
res.status(405).json({ message: "INVALID_METHOD" });
return;
}
// Variables from the client side
var name = req.body.name;
var email= req.body.email;
var subject= req.body.subject;
var content = req.body.content;
// auto line break message
const message = content
.replace(/\n/g, "<br>")
.replace(/\r/g, "<br>")
.replace(/\t/g, "<br>")
.replace(/<(?!br\s*\/?)[^>]+>/g, "");
// giving the api key API
sgMail.setApiKey(process.env.KEY_SENDGRID);
// Creating message
const sendGridMail = {
to: "arotiana4612#gmail.com",
from: "kaspersky2mahanaima#gmail.com",
subject: subject,
templateId: "d-b48909edf062437e8442f861a4c8be29",
dynamic_template_data: {
name: name,
email: email,
subject: subject,
content: message,
},
};
// SENDING MESSAGE VIA SENDGRID
(async () => {
try {
await sgMail.send(sendGridMail)
.then((response) => {
console.log(response[0].statusCode)
console.log(response[0].headers)
})
.catch((error) => {
console.error(error)
})
} catch (err){
console.error(err);
res.status(500).json({
error:JSON.stringify(err),
message: "ERROR_WITH_SENDGRID",
});
}
})();
}
And this is the method from the client side that from which I get the data:
const onSubmit: SubmitHandler<Inputs> = async (formData) => {
if (!isLoading) {
setIsLoading(true);
const response = await fetch("/api/contact", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
});
const result = await response.json();
setIsLoading(false);
if (!response.ok) {
console.log("error sending email:",result);
} else {
console.log("ok");
}
return result;
}
};
I want to receive the mail in my inbox. Your help would be very appreciated, I'm strugling

Azure communication services

I am using azure communication services in my react app to send email.
But It is giving CORS error
import { EmailClient } from "#azure/communication-email";
function App() {
const connectionString =
"**************************************************************************************";
const client = new EmailClient(connectionString);
const sender = "1000055393#hexaware.com";
const emailContent = {
subject: "Send email quick start test- JS sample",
plainText:
"Test Email from JS Send Email Sample Application\n\n This email is part of testing of email communication service. \\n Best wishes",
html: "<html><head><title>ACS Email as a Service</title></head><body><h1>ACS Email as a Service - Html body</h1><h2>This email is part of testing of email communication service</h2></body></html>",
};
const toRecipients = {
to: [{ email: "krnsda04#gmail.com", displayName: "Karan S" }],
};
async function main() {
try {
const emailMessage = {
sender: sender,
content: emailContent,
recipients: toRecipients,
};
console.log(sender,"sender");
const sendResult = await client.send(emailMessage);
console.log(sendResult,"result");
if (sendResult && sendResult.messageId) {
// check mail status, wait for 5 seconds, check for 60 seconds.
const messageId = sendResult.messageId;
if (messageId === null) {
console.log("Message Id not found.");
return;
}
console.log("Send email success, MessageId :", messageId);
let counter = 0;
const statusInterval = setInterval(async function () {
counter++;
try {
const response = await client.getSendStatus(messageId);
if (response) {
console.log(
`Email status for {${messageId}} : [${response.status}]`
);
if (response.status.toLowerCase() !== "queued" || counter > 12) {
clearInterval(statusInterval);
}
}
return;
} catch (e) {
console.log("Error in checking send mail status: ", e);
}
}, 5000);
} else {
console.error(
"Something went wrong when trying to send this email: ",
sendResult
);
}
return;
} catch (e) {
console.log(
"################### Exception occoured while sending email #####################",
e
);
}
}
main();
return <h3>hello ${connectionString}</h3>;
}
export default App;
But when running this code, I m getting this error.
Access to XMLHttpRequest at 'https://************************/emails:send?' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In Azure docs, they have given the code in Node.js.
Since Iam using that code in react and accessing from front end, is it showing CORS error?
How to solve this issue?
As you can see in the SDKs and REST APIs docs, ACS Email library is meant to be used in a trusted service environment. This is because there is no reasonable way to protect your connection string in the browser.
In your case, building a Node.js backend and letting your React app talk to it would be a good and preferred solution.

connection failed simple-peer after deployment

I am using simple-peer for video transmission. Its working fine in my local network so I add google's free stun server to connect with people not in my local network. But its throwing error connection failed if I try to connect to anyone outside of my local network and working fine at local network.
React part
const peer = new Peer({
initiator: true,
trickle: false,
stream,
config: {
iceServers: [
{urls: 'stun:stun.l.google.com:19302'},
{ urls: 'stun:global.stun.twilio.com:3478?transport=udp' }
]
}
});
peer.on("signal", signal => {
socketRef.current.emit("sendingSignal", { userIdToSendSignal: userIdToSendSignal, callerId: callerId, signal });
})
})
const peer = new Peer({
initiator: false,
trickle: false,
stream,
config: {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:global.stun.twilio.com:3478?transport=udp' }
]
},
});
//other peer give its signal in signal object and this peer returning its own signal
peer.on("signal", signal => {
socketRef.current.emit("returningSignal", { signal, callerId: callerId });
});
peer.signal(incomingSignal);
})
Nodejs part
const socket = require("socket.io");
const io = socket(server);
const usersInRoom = {}; //all user(socket id) connected to a chatroom
const socketToRoom = {}; //roomId in which a socket id is connected
//verifying token
io.use(async (socket, next) => {
try {
const token = socket.handshake.query.token;
const payload = await jwt.verify(token, process.env.SECRET);
socket.userId = payload;
const user = await User.findOne({ _id: socket.userId }).select('-password');
socket.username = user.username;
socket.name = user.name;
next();
} catch (error) {
console.log(error);
}
});
io.on('connection', socket => {
console.log('Some one joined socketId: ' + socket.id);
socket.on("joinRoom", roomId=> {
console.log('Joined roomId: ' + roomId + " socketId: " + socket.id + ' userId: ' + socket.userId);
if (usersInRoom[roomId]) {
const length = usersInRoom[roomId].length;
usersInRoom[roomId].push(socket.id);
} else {
usersInRoom[roomId] = [socket.id];
}
socketToRoom[socket.id] = roomId;
const usersInThisRoom = usersInRoom[roomId].filter(id => id !== socket.id);
socket.join(roomId); //for message
socket.emit("usersInRoom", usersInThisRoom); //send all socket id connected to this room
});
//client send this signal to sever and sever will send to other user of peerId(callerId is peer id)
socket.on("sendingSignal", payload => {
console.log(payload.callerId);
io.to(payload.userIdToSendSignal).emit('userJoined', { signal: payload.signal, callerId: payload.callerId });
});
//client site receive signal of other peer and it sending its own signal for other member
socket.on("returningSignal", payload => {
io.to(payload.callerId).emit('takingReturnedSignal', { signal: payload.signal, id: socket.id });
});
//from client send message to send all other connected user of same room
socket.on('sendMessage', payload => {
//sending message to all other connected user at same room
io.to(payload.roomId).emit('receiveMessage', { message: payload.message, name:socket.name, username: socket.username });
});
//someone left room
socket.on('disconnect', () => {
const roomId = socketToRoom[socket.id];
let socketsIdConnectedToRoom = usersInRoom[roomId];
if (socketsIdConnectedToRoom) {
socketsIdConnectedToRoom = socketsIdConnectedToRoom.filter(id => id !== socket.id);
usersInRoom[roomId] = socketsIdConnectedToRoom;
}
socket.leave(roomId); //for message group(socket)
socket.broadcast.emit("userLeft", socket.id); //sending socket id to all other connected user of same room without its own
});
});
Error

MongoError: Topology is closed, please connect seems to be related to MongoClient.close() and the client won't work while using it

This question here is closely related but the question and the answer are not very related at all. However, in the comments of that OP's post there is the difficulty of working with .close()... That is where the similarities end.
The issue comes from trying to create an api using the direct nodejs mongodb driver 3.9. I have the client call in the controller because putting it in the server and calling to the client when needed constantly creates a "connect error" so here it is in the controller for full context.
whenever I use .close() in the collection client call it will run once and then every other call after that will cause an error Topology is closed. So, for now I commented it out. I am wondering what is causing this and what might I being doing incorrectly causing this error?
The documentation per the driver states to use this and what the purpose is but it is breaking my api repeatedly.
const express = require('express');
const router = express.Router();
import { MongoClient, MongoCallback, MongoError, MongoNetworkError } from 'node_modules/mongodb';
// const MongoClient = require('node_modules/mongodb').MongoClient;
const dbName = 'HealthCheckup';
const documentName = 'userProfile';
const assert = require('assert');
const url = `mongodb+srv://UserDB:h7srvvvvvvvHFd8#vvvvvvvvvai-cvyrh.azure.mongodb.net/${dbName}?retryWrites=true&w=majority`;
const client = new MongoClient(url, { useNewUrlParser: true, useUnifiedTopology: true});
const findUsers = (client, callback) => {
// Get the documents collection
const collection = client.collection(documentName);
// Insert some documents
collection.find({}).toArray( (err, result) => {
// console.log('err **** -------- ', err);
// console.log('Result -------- ', result);
callback(err, result);
});
}
const createUser = (client, callback, req) => {
// Get the documents collection
const collection = client.collection(documentName);
// Insert some documents
collection.insertOne({
name: req.body.name,
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
tokenId: req.body.tokenId,
userPhoto: req.body.userPhoto
}, (err, result) => {
// console.log('err **** -------- ', err);
// console.log('Result -------- ', result);
callback(err, result);
});
}
// localhost:4021/user
router.get('/', (req, res) => {
client.connect( err => {
const collection = client.db(dbName);
if (!err) {
console.log("Connected successfully to server.");
} else {
console.log('Error in DB connection : ', JSON.stringify(err, undefined, 2));
}
findUsers(collection, (err, result) => {
console.log('err 2222222 -------- ', err);
console.log('Result 2222222 -------- ', result);
if (!err) {
res.send(result);
} else {
console.log('Error retreiving user ', JSON.stringify(err, undefined, 2))
}
console.log('BREAKPOINT 00000000000000000');
// client.close();
});
});
});
You are trying to close the client in a request handler, but your client is global.
If you want to have a global client, do not close it in request handlers.
If you want to close the client in request handlers, create the client in the handler of the same request.
There is a bug on MongoDb: reconnection to the client doesn't work. Seems like it will be fixed in version 4.0.0. For now it's beta. If you don't want to use the beta version then don't close the client. Or recreate it in handlers like it was proposed in previous answer.

Problem with using nodemailer to send email to user on Actions on Google, Dialogflow

I am using nodemailer to send emails to users, when an intent is triggered.
I am creating a promise for the function to send emails using nodemailer.
When running with node index.js, the emails are sent, but when deploying to firebase and invoking the intent with the simulator on actions on google console, i get a webhook error
MalformedResponse
Failed to parse Dialogflow response into AppResponse because of empty speech response.
Here is my code:
When the user invokes this intent, they should receive an email from me.
let sendMails = () => {
return new Promise((resolve, reject) => {
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'my email',
pass: 'password'
}
});
let mailOptions = {
from: 'my email',
to: 'user's email',
subject: 'something',
text: 'here is the email'
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
throw new Error("Error has come");
} else {
let answer = info.response;
return resolve(answer);
// console.log('Email sent: ' + info.response);
}
});
}).catch(error => {
console.log(error);
throw new Error("Error is coming")
})
}
And here is the intent:
app.intent('nda - yes', conv => {
return sendMails().then((answer)=> {
return conv.ask(`<speak>Done. Email is sent. Check your inbox.</speak>`)
})
})`