i'm using the nodemailer library to send emails to my users.
The problem is that some special charachter such us "è" or "à" are not visible.
Can i change the encoding of the subject? in the body is already working.
var mailOptionsUtente = {
from: 'my#email.it', // sender address
to: utente.email, // list of receivers
subject: "non è possibile", // Subject line
html: "HTML...."
};
i know you can add encoding option in your object.
See here
https://community.nodemailer.com/
You can add subject encoding options like that :
var subject = 'non è possibile';
var mail = {
...,
subject: {
prepared: true,
value: '=?UTF-8?B?'+new Buffer(subject).toString('base64')+'?='
},
...
};
source : https://github.com/nodemailer/nodemailer/issues/562
Related
I have a strange problem. I made a small application in node.js, using nodemailer to send emails each day.
And it's working perfectly when I run it from the terminal (for testing).
But when I add a job to crontab, then emails are sent but there is missing some of the content inside.
This is my transporter conf:
// send mail with defined transport object
let info = await transporter.sendMail({
priority: 'high',
from: '"Example" <example#gmail.com>', // sender address
to: 'recip#gmail.com', // list of receivers
subject: 'Example title: '+currentDate, // Subject line
text: '', // plain text body
html: header + missing + carrierStatArr + ending,// html body
attachments: attachments
});
And code for variables to html field:
let carrierStatArr = [], attachments = [];
let header = `<h1>some text ${currentDate}</h1><div><i>some text</br>some text</i></div>`;
let missing = `<h3 style="color:red;">some text: <b>${missingArr}</b></h3>`;
for (let i in checkResultArr) {
let imgName = checkResultArr[i].file;
let correctedImgName = imgName.substring(0,16);
carrierStatArr.push(`<p>Some text <b>${checkResultArr[i].name}</b>,</br>
<span>Some text: <b>${checkResultArr[i].status}</b></span></br>
<span><img src="cid:${correctedImgName}" width="1000px"/></span>
</p>`);
}
//console.log(carrierStatArr);
attachments = checkResultArr.map((file)=>{
let pat = '/var/www/html/public_html/MM1_service/images/';
let fi = file.file;
let fit = fi.substring(0,16);
return {path: pat+file.file, cid: fit};
});
//console.log(attachments[0].path);
let ending = `<hr size="1" width="100%" color="gray"><p><i>some text</i></p>`;
Of course, there are all data in arrays. And as I wrote, when I run this code manually using terminal /node sendmail.js/ it works perfectly, email contains all the information's, text, and images.
But when the script is run automatically by the cron job, the email has only header, missing, and ending variables (and the content from arrays is there) but the rest: carrierStatArr, attachments are missing.
Why is that? Manually work, run by cron not exacly.
Note: I managed to solve my problem by using the 'node-cron' module instead of the system cron. The app is working correctly.
But still I'm curious, from an academic point, why that problem occurred.
I have a problem setting the author of a mail in the "from" field of the RFC2822 mail (here the detail).
The problem is that the author does not appear in the received mail. The "from" field I've set looks like this:
MyName: name.surname#gmail.com
But I also tried:
MyName <name.surname#gmail.com>
None of these work, in the received mail the name is still missing looking at the original mail.
This should work because using nodemailer (with Gmail) and the same value for "from" it works. Can someone explain me what's happening? How can I solve?
EDIT: I report the code I am using as asked in one comment.
I separated the call to the API from the part that generates the mail body, so the call is:
function gmailSend(auth, mail){
const gmail = google.gmail({version: 'v1', auth});
const b64mex=mail.b64enc();
return gmail.users.messages.send(
{auth: auth,
userId: 'me',
resource:
{raw: b64mex}
}
);
}
While the parameter "mail" is generated in this way:
function genMail(candidate, clerk_email, supervisor_email){
return new Mail({from: `MyName: name.surname#gmail.com`, to: candidate.email,
subject: "Test Mail", bcc: supervisor_email,
"reply-to": clerk_email}, genMessage(candidate));
}
Mail simply compose an object that has the properties given in its first parameter, while b64enc() puts all in a string respecting the RFC2822 and encodes it base64.
EDIT2: code for Mail class.
class Mail{
constructor(headers, body) {
if(!headers.to)
throw Error("Recipient missing");
if(headers.subject){
const b64subject=new Buffer(headers.subject).toString("base64")
.replace(/\+/g, '-').
replace(/\//g, '_');
headers.subject='=?utf-8?B?'+b64subject+"?=";
}
Object.assign(this, headers);
this.body = body;
}
b64enc(){
const fields = ["Content-Type: text/html; charset=\"UTF-8\"\n",
"MIME-Version: 1.0\n",
"Content-Transfer-Encoding: 7bit\n"];
for(const prop of Object.keys(this)){
if(prop!=="body")
fields.push(`${prop}: ${this[prop]}\n`);
}
fields.push("\n");
fields.push(this.body);
const str=fields.join('');
const encodedMail = new Buffer(str).toString("base64")
.replace(/\+/g, '-').
replace(/\//g, '_');
return encodedMail;
}
}
EDIT3: I add screenshots of desired and actual behaviour:
Desired behaviour, the hidden info are the sender's email and the receiver's one:
Actual behaviour. The difference is that here there is not "MyName".
What is shown in my email client of course is based on the content of "From:" in the plain email. In the first case it is "My name <email address>", in the second it is just "email address".
In order to show a name, and not just the email address, you can format the from field the following way:
from: '"MyName" <name.surname#gmail.com>'
I'm trying to implement an email price alerts system. In my situation, one email can have multiple price alerts, thus, conflicting with SendGrid when sending the alert as it receives the following error:
message: 'Each email address in the personalization block should be ' +
'unique between to, cc, and bcc. We found the first duplicate ' +
'instance of [xxxxxxx#gmail.com] in the personalizations.0.to ' +
'field.',
field: 'personalizations.0',
help: 'http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#message.recipient-errors'
I have not found anything that shows my use case. The best that I get is to send the same email to multiple different recipients such as: https://sendgrid.com/docs/for-developers/sending-email/personalizations/#sending-the-same-email-to-multiple-recipients
Is this something that can be achieved with SendGrid?!
My function:
function sendEmail (emailz, subject, body) {
const email = {
to: emailz,
from: 'salut#xxxxxxxxx.ro',
subject: subject,
text: body,
html: body
}
return sgMail.send(email)
.catch(error => {
console.error(error)
if (error.response) {
const {message, code, response} = error;
const {headers, body} = response;
console.error(body);
}
});
}
Actual email sending done:
try {
await sendEmail(
emailul,
'Alerta notificare pret!!!',
`Pretul produsului pe care il urmaresti este de ${pretulCurent} , sub alerta de pret setata de ${pretulDorit}. <br /> Produsul tau este: ${titlul} : ${link} `
)
} catch (e) {
await sendEmail('S-a produs o eroare', e.message)
throw e
}
Any help would be greatly appreciated. If this cannot be done using SendGrid, can you give me some pointers on other services where this situation might apply ?
Okay, if I understand you correctly, the problem here seems to be avoiding duplicates in your to email field. I suggest you check for duplicates before pushing to SendGrid (SendGrid won't do it for you) for each batch/job.
SendGrid accepts either an array of strings, or comma-delimited values, so you could try something like this:
var finalEmailul = [];
// for each email in the list, check - if it doesn't exist, push it in
if(finalEmailul.indexOf(emailul) < 0){
finalEmailul.push(emailul);
};
// then use 'finalEmailul' in your 'sendEmail' function
try {
await sendEmail(
finalEmailul, // <- use here. If you want it to be comma-delimited, use finalEmailul.join(",")
'Alerta notificare pret!!!',
`Pretul produsului pe care il urmaresti este de ${pretulCurent} , sub alerta de pret setata de ${pretulDorit}. <br /> Produsul tau este: ${titlul} : ${link} `
)
} catch (e) {
await sendEmail('S-a produs o eroare', e.message)
throw e
}
I have a scripted pipeline. In one of my steps I want to send different mails based on test results. Here is how I do it now:
if (buildResult == 'SUCESSS'
def email_body="TEST_SUCESS.template"
else
def email_body="TEST_FAILURES.template"
emailext(
subject: "Job '${env.JOB_NAME} [${env.BUILD_NUMBER}] finished",
body: "${SCRIPT,template=$email_body}", // LINE A
recipientProviders: [[$class: 'DevelopersRecipientProvider']],
to: 'XXXX',
from: 'YYYY',
replyTo: 'ZZZZ',
mimeType: 'text/html',
)
I can't have Jenkins expand the value of the variable email_body. I've tried various approaches in the line A:
"${SCRIPT,template=$email_body}"
"${SCRIPT,template=${email_body}}"
'''${SCRIPT,template=$email_body}'''
'''${SCRIPT,template=${email_body}}'''
None of them works. All I get in the email is either:
Groovy Template file [$email_body] was not found in $JENKINS_HOME/email-templates.
or
${SCRIPT,template=$email_body}.
What is the correct way of setting email content if the email content is stored in a variable?
Try to use this example:
String subject = "${env.JOB_NAME} was " + currentBuild.result.toString();
String email_body="TEST_" + currentBuild.result.toString() + ".template"
String body = "SCRIPT,template=" + email_body;
String to="some_mail#mail.com"
String reply="ZZZ"
emailext(subject: subject, body: body, to: to, replyTo: reply);
I'm using phpmailer with the following settings:
$mail->ContentType = 'text/plain';
$mail->IsHTML(false);
...
$mail->Body = $_POST['comments'];
$mail->Body = strip_tags($mail->Body);
I noticed strip_tags() cuts off the text if it hits a single greater than / less than sign (i.e if the user put in one of those characters legitimately).
Given that I have content type = 'text/plain' and ishtml = false, is it even necessary to have strip_tags() in there?
No, it is not neccesary. If you set $mail->isHTML(false) and you write HTML in the email, it is sent like text plain so it doesnt interpret it like HTML.
For example I've just done this:
$mail->ContentType = 'text/plain';
$mail->isHTML(false);
$mail->Subject = 'Your password';
$mail->Body = '<p>Your password is 123</p> Go to google ';
And the mail looks like this:
<p>Your password is 123</p> Go to google