I'm trying to send an e-mail with an attachment using Nodemailer. No matter what I do, if I specify an attachments property, the e-mail comes up empty (no attachments, no html, no text). Sending an e-mail without any attachments works as expected. Here's the code I have so far:
transporter.sendMail({
to: `${toTitleCase(i.nome)} <${i.email}>`,
subject: 'Treinamentos',
text: 'hello!',
html: `Embedded image: <img src="cid:nyan#example.com"/>`,
attachments: [
{
filename: 'newimg.jpg',
path: __dirname + '/src/img/newimg.jpg',
cid: 'nyan#example.com'
}
]
}, (err, info )=> {
console.log(err);
console.log(info);
});
I have also tried using content instead of path, same result. I should also note that the err callback is empty.
I figured it out. I had set 'Content-type': 'text/html; charset=UTF-8' as the header on the transporter object. Removing that line fixed the issue.
Related
I hope you all have a great day. I am coding my own personal website and I have a section called to contact me. The problem I have with this section is that I am trying to send my client email to my email and when I am trying to send their message to my server through Graphql I get this error
[
{
"message": "Syntax Error: Unterminated string.",
"locations": [
{
"line": 3,
"column": 123
}
]
}
]
the request I sent to my server is
'\n mutation{\n sendEmail(EmailInput: {name: "Test name", email: "Test#email.com",
subject: "this is test subject", message: "\n
this is the first line \nthis is the second line\nwhen I have multiple lines I have these problem\n
"}) {\n success\n message\n }\n }\n '
I don't know how to fix it I don't know why I get this error.
I used fetch to send my code backend :
const emailMutationQuery = `
mutation{
sendEmail(EmailInput: {name: "${senderName.value}", email: "${senderEmail.value}", subject: "${senderSubject.value}", message: "
${senderMessage.value}
"}) {
success
message
}
}
`;
const result = await fetch("http://localhost:2882/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: emailMutationQuery,
}),
});
const convertedResult = await result.json();
GraphQL supports variables, which can be used to supply input data separately from the query. The variables are just a separate JSON-encoded object. This avoids syntactic difficulties (and potential security risks!) from trying to embed the inputs directly in the query.
For this you'd write a fixed query, that declares and uses the variable, but doesn't depend on the per-request inputs
const emailMutationQuery = `
mutation SendEmail($emailInput: SendEmailInput!) {
sendEmail(EmailInput: $emailInput) {
success
message
}
}
`;
You'd then create a second object containing the variable(s). The top-level keys match what you declare in the GraphQL operation line, and their content matches the corresponding GraphQL input types.
const variables = {
emailInput: {
name: senderName.value,
email: senderEmail.value,
subject: senderSubject.value,
message: senderMessage.value
}
};
Note that this is an ordinary Javascript object, and we haven't quoted or escaped anything here.
Now when we make the request, we send the query and variables together
const result = await fetch("http://localhost:2882/graphql", {
...,
body: JSON.stringify({
query: emailMutationQuery,
variables: variables
})
});
Things like newlines in the message content will be escaped in the variables block, and get passed through correctly to the underlying GraphQL engine.
I actually find a solution for it but feel free to share your answers here. The solution I found for this problem was that you have to use JSON.stringify() for the textarea. you have to pass your textarea value to this function and js will take care of the rest. my code now looks like this
const emailMutationQuery = `
mutation{
sendEmail(EmailInput: {name: "${senderName.value}", email: "${senderEmail.value}", subject: "${senderSubject.value}",
message:${JSON.stringify(senderMessage.value)}}) {
success
message
}
}
`;
I hope this help you guys.
This is from: https://www.openproject.org/docs/api/endpoints/attachments/
To add an attachment to a work package, a client needs to issue a
request of type multipart/form-data with exactly two parts.
The first part must be called metadata. Its content type is expected
to be application/json, the body must be a single JSON object,
containing at least the fileName and optionally the attachments
description.
The second part must be called file, its content type should match the
mime type of the file. The body must be the raw content of the file.
Note that a filename must be indicated in the Content-Disposition of
this part, however it will be ignored. Instead the fileName inside the
JSON of the metadata part will be used.
I believe I'm understanding a general idea of what is occurring, i.e. how multipart/form data works as an enctype, why it exists, I get that I need to send two parts in the above description. One a JSON Object, and the other a file that also has a content disposition set with a filename parameter...
Beyond this very loose "understanding" I couldn't/wouldn't be able to translate this to a fetch statement or doing something in Postman (when I've tried it's summarily failed).
Could someone point me in the right direction to assist in my endeavor?
(note, I generally use Fetch/javascript for any such activities, if that matters...)
My last, not working, code:
const formData = new FormData();
let uploadFile = articleImages[0].src;
let jsonPayload = { "metadata": { "fileName": "randomfilename.jpg", "description": "Random Description" }};
console.log(jsonPayload);
formData.append( "metdata", jsonPayload );
formData.append( "file", uploadFile);
for (const value of formData.values()) {
console.log(value);
}
fetch('https://***/api/v3/work_packages/***/attachments', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('apikey:***'),
'referrer': '',
'credentials': 'include',
'mode':'cors'
},
body: formData,
})
This would give the error:
{_type: 'Error', errorIdentifier: 'urn:openproject-org:api:v3:errors:PropertyConstraintViolation', message: "File can't be blank.", _embedded: {…}}
errorIdentifier: "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
message: "File can't be blank."
_embedded: {details: {…}}
_type: "Error"
[[Prototype]]: Object
Thank you all.
To answer recent comments:
In postman:
"_type": "Error",
"errorIdentifier": "urn:openproject-org:api:v3:errors:MultipleErrors",
"message": "Multiple field constraints have been violated.",
"_embedded": {
"errors": [
{
"_type": "Error",
"errorIdentifier": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation",
"message": "File can't be blank.",
"_embedded": {
"details": {
"attribute": "filename"
}
}
},
{
"_type": "Error",
"errorIdentifier": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation",
"message": "The content type of the file cannot be blank.",
"_embedded": {
"details": {
"attribute": "contentType"
}
}
}
]
}
See image for what I sent:
Ahoi rogelio,
first thing is, that your metadata JSON is nested too much. Value should be { "fileName": "randomfilename.jpg", "description": "Random Description" }, without the metadata key on top.
Second, I do not really know, how fetch constructs its requests, but this is an example of how the request body should look like:
-----------------------------35500998851541290908403510937
Content-Disposition: form-data; name="metadata"
{"fileName":"test.txt"}
-----------------------------35500998851541290908403510937
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
This is a test text.
-----------------------------35500998851541290908403510937--
In addition, it would be interesting to know, what is in the embedded details of the response error. ;)
Hope I can help!
Edit
I built this request in Postman, and it works without flaws. This is how to setup the request: postman setup
Below is the message object used to send emails.
message = {
to: toEmail,
from: emailInfo.emailFromAddress,
subject: emailInfo.emailSubjectTemplate,
attachments: [
{
filename: fileName,
content: base64str,
contentId: fileName,
disposition: "attachment"
}
],
html: emailMessageBodyTemplate
};
The content is encoded into a base64 string by the following below code.
const base64_encode = file => {
var bitmap = fs.readFileSync(file);
return new Buffer(bitmap).toString("base64");
};
I don't know where I m going wrong but I'm getting the error as follows.
message:"The content value must be a string at least one character in length."
but the content is not empty when I debug it is a base64 string.
Please help.
On this page it describes exactly your error.
I believe in this error content means your message or a text as error describes
You may not send an email with no content.
And as per the API docs,you are missing a required parameter content.
message = {
to: toEmail,
from: emailInfo.emailFromAddress,
subject: emailInfo.emailSubjectTemplate,
content:[
{
type : 'string',
value : 'message'
}
],
attachments: [
{
filename: fileName,
content: base64str,
contentId: fileName,
disposition: "attachment"
}
],
html: emailMessageBodyTemplate
};
Hope this helps.
I've encountered the same issue and in my case I used 'xlsx' npm lib, to implement the solution as follow:
const workbook = XLSX.utils.book_new();
const ws = XLSX.utils.aoa_to_sheet(data);
XLSX.utils.book_append_sheet(workbook, ws, 'Accounts');
// write the file in base64 format
const report = XLSX.write(workbook, { type: 'base64', compression: true });
const attachment = {
content: report,
filename: `MyReport.xlsx`,
type: 'text/html',
disposition: 'attachment'
};
How do I template SendGrid's content with Nodejs?
I am trying to send emails from contact form in an application using SendGrid. I have a Google Cloud Function that I am calling via an HTTP post. I am able to pass in the form data as a JSON object to my Google Cloud Function, and display a raw JSON object in my email content, but when I try to template my SendGrid content, the JSON object's properties keep coming back as undefined. How do I display my different formData properties within my SendGrid email content?
Here is the code:
const functions = require('firebase-functions');
const sg = require('sendgrid')(
process.env.SENDGRID_API_KEY || '<my-api-key-placed-here>'
);
exports.contactMail = functions.https.onRequest((req, res) => {
contactMail(req.body);
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.send("Mail Successfully Sent!");
})
function contactMail(formData) {
const mailRequest = sg.emptyRequest({
method: 'POST',
path: '/v3/mail/send',
body: {
personalizations: [{
to: [{ email: 'my.email#gmail.com' }],
subject: 'Contact Us Form Submitted'
}],
from: { email: 'noreply#email-app.firebaseapp.com' },
content: [{
type: 'text/plain',
value: `
You have received a contact us form submission. Here is the data:
Name: ${formData.userFirstName} ${formData.userLastName}
Email: ${formData.userEmail}
Subject: ${formData.formSubject}
Message: ${formData.formMessage}
`
}]
}
});
sg.API(mailRequest, function (error, response) {
if (error) {
console.log('Mail not sent; see error message below.');
} else {
console.log('Mail sent successfully!');
}
console.log(response);
});
}
This displays undefined for each template expression.
However if my content section is set to this:
content: [{
type: 'text/plain',
value: formData
}]
Then the email content is displayed as a raw JSON object.
How do I clean up my SendGrid email content and display my JSON data in a formatted, cleaner way?
The problem was my req.body was a text string, not a JSON object.
Using const formData = JSON.parse(req.body); and then passing this variable to contactMail will properly display the JSON object's properties in an ES6 template literal.
i'm trying to use the emailjs (https://github.com/eleith/emailjs) for send emails with nodejs, but, it gives me an error: { [Error: timedout while connecting to smtp server] code: 4, smtp: undefined }
I'm trying to use hotmail, but I can use other, I only want this working. Any idea please?
var email = require("emailjs");
var server = email.server.connect({
user: "xxx#hotmail.com",
password:"xxxyyyy",
host: "smtp-mail.live.com",
ssl: true
});
// send the message and get a callback with an error or details of the message that was sent
server.send({
text: "i hope this works",
from: "you <xxxxxx#hotmail.com>",
to: "someone <zzzzz#hotmail.com>",
//cc: "else <else#your-email.com>",
subject: "testing emailjs"
}, function(err, message) { console.log(err || message); });
I tested with the code below (using gmail) and it is working:
var email = require('emailjs');
var server = email.server.connect({
user: 'nodejsiscool#gmail.com',
password: 'stackoverflow',
host: 'smtp.gmail.com',
ssl: true
});
server.send({
text: 'Hey howdy',
from: 'NodeJS',
to: 'Wilson <wilson.balderrama#gmail.com>',
cc: '',
subject: 'Greetings'
}, function (err, message) {
console.log(err || message);
});
In my console the output is:
{
attachments: [],
alternative: null,
header: {
'message-id': '<1433256538447.0.5970#Wilsons-MacBook-Pro.local>',
date: 'Tue, 02 Jun 2015 10:48:58 -0400',
from: '=?UTF-8?Q?NodeJS?= <>',
to: '=?UTF-8?Q?Wilson?= <wilson.balderrama#gmail.com>',
cc: '',
subject: '=?UTF-8?Q?Greetings?='
},
content: 'text/plain; charset=utf-8',
text: 'Hey howdy'
}
Indeed I have received in my inbox the email message.
I suspect that you should use the host smtp.live.com instead of smtp-mail.live.com
Note: The account (nodejsiscool#gmail.com) used is a valid one I just created for testing purposes.
Using Gmail
First: Required activate the use less secure apps at your own risk as indicated in the Gmail documentation. I use an account not very important for my tests:
https://myaccount.google.com/u/2/lesssecureapps?pageId=none
After:
var email = require("emailjs");
var server = email.server.connect({
user: "YOUR_ACCOUNT#gmail.com",
password:"YOUR_PASSWORD",
host: "smtp.gmail.com",
ssl: true
});
server.send({
text: "Hello world",
from: "YOUR_NAME <YOUR_ACCOUNT#gmail.com>",
to: "FRIEND_NAME <FRIEND_ACCOUNT#gmail.com>",
subject: "Hello"
}, function(err, message) { console.log(err || message); });
Additional Note: About how set "from" and displayed name in Gmail inbox:
Example 1:
Set "from" with only name.
from: "YOUR_NAME", // Only name
In inbox display <>
YOUR_NAME <> Hello 18:11
Example 2:
Set "from" with name and emial.
from: "YOUR_NAME <YOUR_ACCOUNT#gmail.com>", // Name and email
In inbox not display <>
YOUR_NAME Hello 18:11
Make sure you are linking the emailjs files correctly (check var email) or it won't work.
//Email stuff
var email = require("./node_modules/emailjs/email");
var server = email.server.connect({
user: "EMAIL#gmail.com",
password:"INSERTPASSWORDHERE",
host: "smtp.gmail.com",
ssl: true
});
//If button is clicked then send email
server.send({
text: 'Hello World! \n\n Regards,\n INSERTNAMEHERE \n',
from: 'Name',
to: 'Name <EMAIL#gmail.com>',
cc: '',
subject: ''
}, function (err, message) {
console.log(err || message);
});
make sure you have installed exact package with same version
npm i emailjs#1.0.11
and try below code
var email = require("emailjs");
var server = email.server.connect({
user: "your-email#gmail.com",
password: "your-password",
host: "smtp.gmail.com",
ssl: true
});
server.send(
{
text: "Hey howdy",
from: "NodeJS",
to: "Wilson <your-email#gmail.com>",
cc: "",
subject: "Greetings"
},
function(err, message) {
console.log(err || message);
}
);
seems latest version is not working its using es6 exports "emailjs#1.0.11" but version still works fine .
also don't forget to enable less secure setting for email address you are using with password .
I think you can use this version
emailjs#2.2.0
,
For me, this is working in version 2.2.0
where version 3.0 and above will show the error.
npm i emailjs#2.2.0
here is the example