Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Imagine you could send emails with JavaScript, multipart, and with attachments?! How would the code look like? This is what I came up with. Forks & comments much appreciated! #nobackend #dreamcode
// send text email
sendEmail({
subject: "Hello, World!",
text: "This mail has been sent from the frontend",
to: "joe@exam.pl"
})
// send multipart text / html email
sendEmail({
subject: "Hello, World!",
text: "This mail has been sent from the frontend",
html: "<p>This mail has been sent from the frontend</p>",
to: "joe@exam.pl"
})
// send multipart with attachment
sendEmail({
subject: "Hello, World!",
text: "This mail has been sent from the frontend",
html: "<p>This mail has been sent from the frontend</p>",
to: "gregor@martynus.net",
attachments: [
convert( document.body ).to("screenshot.png"),
{ filename: "info.text", data: "Some info about the page"}
]
})

mackuba commented Apr 29, 2013

This seems like a really bad idea in terms of security. If your JS code can send any email using your servers, then anyone can send any emails using your servers by just opening a JS console and calling that function with any arguments they want. How would you prevent this from being used for spam?

Owner

gr2m commented Apr 30, 2013

Yeah, spam is definitely something that has to be takin care of. I agree that might be a complex problem depending on how you use email in your app, for example if accounts are required or not.

But this problem has been resolved before and I don't think it should make the frontend API more complicated than what I suggested. Don't you think?

cayblood commented May 3, 2013

I think this would be more secure if you had an api that allowed people to send emails to specific individuals where a trusted relationship had already been established and you ensured that they hadn't exceeded a certain quota. So perhaps the api would require authentication and accept one or more recipient_ids and validate them against a database.

To send to multiple accounts at the same time, the to property should be an array. It is also necessary to add the cc, bcc properties

// send text email
sendEmail({
  subject: "Hello, World!",
  text: "This mail has been sent from the frontend",
  to: ["joe@exam.pl", "jane@exam.pl"],
  cc: [...],
  bcc: [..]
})
Owner

gr2m commented May 10, 2013

@cayblood

I agree to some extend, I wouldn't change the API though. Instead, when I try to send an email, it should return an error like "you are not allowed to send an email to XYZ@example.com." or "You have to create an account before sending emails". And these errors could be returned by backend logic.

This way, we could keep the API nice an clean, while still being flexible on the security constraints of your app's backend.

@CodeMaxter

Yeah, totally, great point! I'd also suggest that both should work, passing arrays to to, cc and bcc as well as string of multiple email addresses, separated by ; or ,

Re: Spam. Rate limiting will help greatly, like 1 email per minute, maybe made more lenient the user has a email verified account (again with IP rate limiting on account creation).

AMorgaut commented Jun 3, 2013

1) Regarding the syntax, I think you should allow the basic alternative signature:

sendEmail(to[, subject[, body[, options]]]);

-> sendEmail(to) would be like sending a ping notification
-> sendEmail(to, subject) would be like sending a SMS
-> sendEmail(to, subject, body) would be like sending a basic Email

If the body parameter is a DOM Node instead of a string, the email format could be automatically set to HTML
With contenEditable, this would make easy to create email editors

To manage success / errors, you would also need to support either:

  • a readystate (as in XHR and other HTML5 APIs)
  • a Future / Promise interface (see DOM Future)

ex:

sendEmail(params).done(onsuccess, onerror); // DOM Future like

2) Regarding security

You may be allowed to send an email to anyone as long as you have been authenticated before and as your own email address (which will be used as default "From" email address) has been verified for this account.

Another option could be to consider OAuth from email providers (gmail, Yahoo Mail, outlook.com...) to "grant" usage of a "sender" email address.

Owner

gr2m commented Jun 23, 2013

you don't need success / error callbackes, you can just do

sendEmail(params).done(onsuccess).fail(onerror);

In some ways, you could see this as a browser-enhancement of mailto: links. I believe external e-mail apps do provide the level of inter-app communication necessary. At the level, you're still forcing the user to click send on their client (outlook, gmail) which enforces a level of security and spam-control.

Where it gets hard is truly seamless email sending, then the e-mail client or browser-based smtp needs to trust the browser app and the website to not be a malicious website, and be a real person. Only then, would callbacks be realistic - otherwise, it's fire and forget.

Why a function allowing request permissions from a browser? It simplifies the current "stack of infobars/notifications" problem using a simple dialog and also the "security" problem allowing, in this case, the webpage use the user's e-mail client, only if allowed.

requestPermissionsFor(permissions, [callback]) // returns promisse: callback is the same as .then()

// example: email client
requestPermissionsFor('email notifications').fail(function (error) {
    // a error occurred, example: incognito mode is enabled
}).done(function (permissions) {
    // permissions = {email: true, notifications: false}

    // alerts the user that the website can send emails but it
    // will not show any notifications of new received emails
});

orbitbot commented Jul 8, 2014

This might be slightly offtopic, since I stubled upon this discussion from the noBackend website while searching for resources on offline applications, but services like Mailgun ( http://www.mailgun.com/ , no affiliation) offer more or less this exact API already. API usage is through HTTP requests, which easily could be wrapped for example with Angular to something that can be used as you discuss above.

Owner

gr2m commented Jan 19, 2015

I understand the security concerns, but please understand that this is out of scope here. Think of it as a wrapper to what ever is used behind the curtain to securely send multipart emails. If http requests to a backend are used, then it's the back-end's job to make this secure. The front-end just expresses the intent to do so, and if the server denies is, the error will be transparently passed to the returned promise.

Using CORS it will prevent sending emails from not allowed pages. But it's difficult to find a way that solves everything. 😢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment