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.
Related
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 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 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
I am editing online available snooze script for gmail, where i would like to bring back an email unread, in inbox and on top of the list. I am able to make it unread, and bring back to inbox based on the available script, but to bring on top of the inbox, i am forwarding the email to myself. By this, I am able to get the email thread on top of the list, but when an email which is snoozed has an attachment, it forwards the email with attachment. I have tons of emails, and have limited available space. Hence i am ending up using extra storage for duplicate attachment which is unneeded.
I would like to forward the email, without attachment. Below is my current script:
var firstThread = page[i];
var giattachment = null;
var sub = firstThread.getFirstMessageSubject();
var newsub = "Reminder: " + firstThread.getFirstMessageSubject() + " : ";
var id = newsub + firstThread.getPermalink();
var messages = firstThread.getMessages();
var totalThreadCount= firstThread.getMessageCount();
for (var j = 0; j < messages.length; j++) {
var forwardlength=messages.length-1;
if(j == forwardlength) {
if (MARK_UNREAD) {
messages[j].markUnread();
}
messages[j].forward(userEmail,{subject: newsub, from:userEmail, name: EmailFrom, body: newbody, attachments:giattachment});
}
}
Inspite of this, the email gets forwarded with an attachment. Please advise..
Thanks in advance
To selectively forward messages, use filters to create rules that forward in response to message attributes or content.
You can filter messages by properties such as the sender, subject date, size, and message contents. Any query using Gmail's advanced search syntax can also be used in a filter. Try to set criteria.hasAttachment=true to false.
For more information, follow this link: https://developers.google.com/gmail/api/v1/reference/users/settings/filters
You can't forward using Class GmailMessage because it forces you to forward the original attachments. While unforunately undocumented, its advanced parameter attachments can only add new attachments.
However, you can forward by creating a new message using Class MailApp instead, in your case it would be:
var from, firstThread = page[i];
var sub = firstThread.getFirstMessageSubject();
var newsub = "Reminder: " + firstThread.getFirstMessageSubject() + " : ";
var id = newsub + firstThread.getPermalink();
var messages = firstThread.getMessages();
var totalThreadCount= firstThread.getMessageCount();
for (var j = 0; j < messages.length; j++) {
var forwardlength=messages.length-1;
if(j == forwardlength) {
if (MARK_UNREAD) {
messages[j].markUnread();
}
from = message.getHeader('From');
if (from.indexOf(' <') > -1)
from = from.substring(0, from.indexOf(' <'));
else
from = '';
MailApp.sendEmail(userEmail, newsub, '', {htmlBody: messages[j].getBody(), name: from, replyTo: message[j].getFrom()});
}
}
Changes:
Removed your var giattachment = null;
Replaced your messages[j].forward with MailApp.sendEmail
Used messages[j].getBody() to simulate the original body
Added the original sender's name as the "sender's" name
Added the original sender's address as reply-to
The last 2 points mean the forwarded message will arrive from "someone else's name" <your#address> which for most recipients will appear like a true forward.
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