Having issues sending "base64" email "attachments" using "#sendgrid/mail" in "nodejs" - node.js

So, basically I want to send a base64 encoded .zip file as email attachment in #sendgrid/mail. The file is saved in MongoDB like this,
I am fetching the data and converting the "file.buffer" which is a binary data to base64 using .toString("base64") something like this,
console.log('Converting to base64')
plugin.file.buffer = plugin.file.buffer.toString('base64')
and it gets perfectly converted into base64 (I know it is working because I am also using that "plugin.file" in .ejs file as a download button something like this,
<a class="btn btn-success btn-sm" download="plugin.zip" href="data:application/zip;base64,<%- plugin %>" role="button">Download</a>
So, now I will be using that "plugin" to send a email to the user, so I am doing something like this just before rendering the ejs page,
if (req.session.email) await sendMail(req.session.email , "Thanks for purchasing" , "Here is your delivery!" , plugin)
res.render('success' , {payment , type: "Payment" , discord , plugin: plugin.file.buffer})
It basically checks if the email of the user is stored in "sessions" i.e. logged in, if yes it sends a email and then renders the success page!
So, the issue is in the email.js file sendMail() function. It is neither sending me the email nor the attachment.
Before showing the code inside that function(), my api keys etc are correct as I am also sending a mail whenever the user creates an account and in that case, everything is working fine and the mail is being sent. But whenever I include the attachment logic, neither the mail nor the attachment is being sent! So, here is my code:-
const { MAILER_API_KEY } = require('../config.json')
const mailer = require('#sendgrid/mail')
mailer.setApiKey(MAILER_API_KEY)
async function sendMail(email , subject , text , plugin) {
mailOptions = {
to: email,
from: 'zoomdev.code#gmail.com',
subject: subject,
text: text
}
// if this if statement is false i.e. plugin is undefined(whenever the user is signing up, he/she doesnt need attachment or stuff. The attachment email is being sent whenever the payment is completed and the file is being sent to the user) it works fine. But sending an attachment doesn't work. The email and attachment doesn't get sent!
if (plugin) mailOptions.attachments = [{
content: plugin.file.buffer,
filename: plugin.file.originalname,
type: 'application/zip', // Here, I have also tried using "application/x-zip-compressed", the type saved in the database and it is the same! :(
disposition: 'attachment'
}]
await mailer.send(mailOptions).then(res => {
console.log(JSON.stringify(res))
return true
}).catch(err => {
console.log(JSON.stringify(err))
return false
})
console.log('Mail sent to ' + email)
}
module.exports = { sendMail }
Whenever sending the attachment email, I am getting this in console,
Executing Payment
Converting to base64
Updating user
// ^ these are something else. Ignore them
// this is the JSON.stringify(... console.log in sendMail function last lines
[{"statusCode":202,"body":"","headers":{"server":"nginx","date":"Fri, 22 Oct 2021 06:57:18 GMT","content-length":"0","connection":"close","x-message-id":"QpxSudqkRGytDU7YFleVgA","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"}},""]
Mail sent to <my email , I have edited this part for privacy, but it correctly logs the email>
Note:-
I am using express#^4.17.1
#sendgrid/mail#^7.4.7
I have checked spam folder and everything

Twilio SendGrid developer evangelist here.
Using a Gmail address as your from address is not a good way to get your emails delivered. Doing so means you are spoofing an email address, even if it is your email address.
When you are spoofing an email address like that, the email server is unable to prove that it has permission to send emails for that address. SPF and DKIM are methods you can use to prove that you control the domain the email is coming from, but when you use a Gmail address (or any other mailbox provider) then you will appear to be spoofing and receiving mailboxes may choose to discard your emails or land them in the spam inbox.
You may have managed to send and receive your account creation emails with this method, but mailbox providers will be a lot more restrictive when it comes to receiving emails with attached zip files. The whole thing appears suspicious and the mailbox will likely reject it, send it spam, or silently delete it.
The advice here is just don't send emails from a domain that you don't control. What you should do is get a domain that you want to send emails from, set up domain authentication for that domain and you will have a much better chance of landing your emails in your users' inboxes than by spoofing Gmail.

Related

Should I sanitize a text from a contact form before sending it to my email?

I have a contact form on a React app. When the user sends the message, it hits a /contact route on my node server. This route calls a MailService, that dispatches the text to my own gmail address.
It works, but what if someone writes shady scripts such as <iframe onLoad="do-nasty-stuff"> instead of a regular message? Will the text be safe by nature because of email providers (it would be pure html or text after all) or should I sanitize it before sending it to me?
If I must sanitize the text, what is the best way to do it in node/express?
The code looks like this:
export class MailControler {
static contact({ email, topic, message }: ContactForm) {
return transporter.sendMail({
from: email,
to: myemail,
subject: topic,
html: message, // TODO: SANITIZE MESSAGE ?
});
}
}

Email is not receiving in recipient's email box while using sendgrid in protractor

I am using protractor-cucumber framework.I am tryig to implement sendgrid method for email sending.For that i have used api from https://sendgrid.com/free/. I am using sendgrid/mail version 5.2.3 and used below code.
const sgMail = require('#sendgrid/mail');
var env=require('../support/sendgrid.js');
sgMail.setApiKey(env.SENDGRID_API_KEY);
console.log(env.SENDGRID_API_KEY);
const msg = {
to: 'xx#gmail.com',
from: 'xxx#gmail.com',
subject: 'Sending with SendGrid is Fun',
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>',
};
sgMail.send(msg);
I am exporting the api from sendgrid.js(i am able to successfully launch the api to the code).When i ran the above code initially, the email not received, then i directly hardcoded the api in the code, then it worked.So i again try to export it from the sendgrid.js file.That time also it worked.But after running the code 2,3 times then again the email was not receiving in the recipient list.I am not understanding why this behave inconsistently.Also i am not able to console whether there is a success or failure.How can we catch/print the error here.Can anyone help me.Thanks in advance

Communication between client and server in Angular 2+

I am using NodeMailer for mail service. I have to get an email address from a field in client side and send that value to app.js where my nodemailer code resides.
client side
ngOnInit() {
this.forgotForm = this.formBuilder.group({
email: this.email,
});
}
sendmail() {
}
app.js, Nodemailer code (I have to get email id for to address here)
let mailOptions = {
from: 'xyz#gmail.com',
to: '',
subject: 'Test Mailer',
text: 'I am testing Nodemailer to send email.',
};
You Should Consider Looking/ Learning Angular and then going into forms . and then into http modules which will help you post data to services
This is a gist not the actual answer
There are a lots of ways to get this done , using normal inputs and getting data from that input using button control or using Forms[the best approach] as you might have other details to send as well.
There are two kind of froms in Angular Template Driven or Reactive Forms.
After getting the details in your form you will need to post it to a Rest service i am guessing. For that you will need to look at Angular Http Client Module
Please look at those links for more detailed Info on them.
You need to use services in angular in order to do this. in terminal set the path to a folder where you want create service, and then use the command ng generate service <service_name> . This will create a file service_name.service.ts. You can refer https://codecraft.tv/courses/angular/http/overview/ or https://angular.io/tutorial/toh-pt4 for more details.
You can use APIs along with http methods get, post, put, delete etc. to complete your task.
In respective component.ts file create a variable email like:
email =string;
In the html file bind the input field with ngModel as:
[(ngModel)]="email"
Then make a function in service.ts that accepts email as arguments
endMail(email) {
//make api call using http method(say post)
// supply email
let url = <APIURL>
return http.post(url, {email: email});
}
Again in component.ts import this service and instantiate in constructor and use a method to call service

How to query how many gmail accounts are logged in?

For a webExtension I'm trying to check the gmail inboxes by sending a xmlhttprequest to:
https://mail.google.com/mail/u/0/feed/atom
https://mail.google.com/mail/u/1/feed/atom
https://mail.google.com/mail/u/2/feed/atom
... and so on for each account. I want to do this for all currently logged in accounts, but I dont know how to find out that number.
Of course, there is a dumb way, in that I just keep incrementing the u/#/ until I loop back to /u/0/, and do a check there.
But that is slow, since I'd then have to wait for the async to return, hopfully there will be a better way.
Not sure about gmail specifically, but you could use browser.cookies.getAll to read all the user cookies for "mail.google.com" (or accounts.google.com or similar).
This assumes you know the name of the cookie(s) you are looking for, so that you can infer on how many accounts the user is logged in.
Also, make sure to add the cookies permission to your manifest.json
browser.cookies.getAll({ domain: 'mail.google.com' })
.then(cookies => {
// do something with the cookies
});
If instead you can assume that each gmail inbox is open in some tab, then you could just query all the current tabs:
browser.tabs.query({ url: "https://mail.google.com/mail/u/*" })
.then(tabs => {
tabs.forEach(tab => {
// do an XHR request to tab.url or just extract the inbox ID for later use
});
})

How to send Share-point Document using mail attachment from Node Mailer

I am using Node Mailer to send email from node application. Now this mail contains attachment which is a share point link and looks something like below -
{ // use URL as an attachment
filename: 'license.txt',
path: 'https://raw.github.com/nodemailer/nodemailer/master/LICENSE'
}
The problem is when I send this mail it gives me 403 forbidden error which I understand is due to the share point link needs authentication. My question is how do I pass the authentication and which type of authentication node mailer would accept for fetching the share point document as an attachment.

Resources