Use Javascript to create an HTML email in Microsoft Outlook
Asked Answered
S

6

35

I'd like to create an email from a Javascript web application. I'm completely aware of the many SO questions on this (e.g. Open Outlook HTML with Chrome). There are problems with the typical answers:

  1. Mailto: link: This will let you create an email, but only in plain text (no HTML) and it does not allow for attachments.

  2. Activex: IE only, my application needs to run in Firefox and Chrome too. FF & Chrome plug-ins to allow ActiveX are security hazards and seem to be buggy.

  3. Server-side sends via SMTP: The email does not end up in the "Sent" folder for the user. Plus hurdles letting the user edit HTML in the browser and attach files.

  4. Create an Outlook .MSG file: There seem to be no libraries and little written about doing this. Apparently the file format actually has an entire FAT file storage system embedded.

Key differences between many other SO questions and mine:

  • I do have access to the client machines, so I could install helper applications or add-ins, change settings as needed, etc.
  • The interface does not need to actually send the mail, it only needs to set it up for the user.
  • I also need to be able to give the email an attachment from JS (e.g. a PDF).

I cannot be the first web app developer to face this and yet I'm unable to find a solution either commercial or open source.

Update:

I used the EML file method and it works well so far. Here's my JS code to create and trigger it:

var emlContent = "data:message/rfc822 eml;charset=utf-8,";
emlContent += 'To: '+emailTo+'\n';
emlContent += 'Subject: '+emailSubject+'\n';
emlContent += 'X-Unsent: 1'+'\n';
emlContent += 'Content-Type: text/html'+'\n';
emlContent += ''+'\n';
emlContent += htmlDocument;

var encodedUri = encodeURI(emlContent); //encode spaces etc like a url
var a = document.createElement('a'); //make a link in document
var linkText = document.createTextNode("fileLink");
a.appendChild(linkText);
a.href = encodedUri;
a.id = 'fileLink';
a.download = 'filename.eml';
a.style = "display:none;"; //hidden link
document.body.appendChild(a);
document.getElementById('fileLink').click(); //click the link
Simplex answered 14/1, 2015 at 20:28 Comment(6)
Your question is somewhat ambiguous. Your title and tags indicate you want to use JavaScript, but your "key differences" state that you can use helper application and add-ins, which are not (necessarily) JavaScript. It appears as though you want us to do some searching for you to find a solution, which is generally a bad fit for SO.Forrest
...but I would be using JavaScript to create the message and whatever else was needed to interface with some unknown solution. I've hunted high and low myself for a solution. I did not ask anyone else to look for me, I asked if someone had an approach that I had not thought of.Simplex
I like the approach, it adheres to browser sandbox rules (the user doesn't have to open the EML file they download) whilst appearing to give exactly what is needed. I will definitely find a use for this technique!Cornelius
@James Bell Can you please provide your filename.eml file? I am interesting how you are adding attachments.Ciera
@yurin The .EML file works for passing an HTML email to Outlook, but I could not find any way to add an attachment.Simplex
Unpleasant update: Chrome (since about v.46) has begun flagging .EML files as possibly malicious. No idea what horrors a text file could cause but I assume they had their reasons.Simplex
D
31

MSG file format is documented, but it is certainly not fun... Why not create an EML (MIME) file?

The suggestion is to use the EML (MIME) format. According to the OP, they considered the MSG file format (#4), but were discouraged by its complexity and lack of JS libraries that process that format. If MSG file was considered, MIME is a much better choice - it is text based, so no special libraries are required to create it. Outlook will be able to open it just as easily as an MSG file.

To make sure EML message is treated as an unsent message by Outlook, set the X-Unsent MIME header to 1.


The simplest EML file would look like the following:

To: Joe The User <[email protected]>
Subject: Test EML message
X-Unsent: 1
Content-Type: text/html

<html>
<body>
Test message with <b>bold</b> text.
</body>
</html>
Degradable answered 14/1, 2015 at 20:46 Comment(14)
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post.Annunciator
No offense Nicolas, you do sound like a native English speaker, and I am pretty sure you realize that my suggestion is to use the MIME file format. I am sure you can see that "Why not create an EML (MIME) file?" is a polite way of saying "You really need to use the EML (MIME) format".Degradable
Have you tried this approach, and did it work? What resources did you use to learn the format?Simplex
I am not a JavaScript developer, I work with Outlook. Try the sample EML file above. EML/MIME format is documented in RTC822: tools.ietf.org/html/rfc822Degradable
This idea panned out and does indeed give me a way to make Outlook HTML emails. I have not tried attachments but this solves my immediate need very nicely. Props to @CalvT for developing it more.Simplex
Kudos for the "X-Unsent: 1" - just what I was looking for.ThxSuccess
- .eml files are not supported in Outlook 2016.Marchal
@Gintas K - of course they are supported by Outlook 2016. Create an EML file and open it from Windows Explorer.Degradable
@DmitryStreblechenko Or is it Office365 taht doesn't support it? I get "You have a newer version of Office installed ... pleasse remove these new products and try again." when trying to open .eml files..Marchal
Did you end up with two version of Office installed somehow? Have you tried to reinstall Office? Do you get the same problem with MSG files?Degradable
@DmitryStreblechenko I've only got one version installed - 2016, which is part of the Office365 plan. MSG files are absolutely fine..Marchal
Have you tried to reinstall Outlook? This does not seem to be related to the original question. You might want to ask your question at Super User.Degradable
Where is a good resource to see the specifications for *.eml files? I would like to read more about Content-Type, X-Unsent, and see what other options exist. Thank you!Khasi
You start at en.wikipedia.org/wiki/MIME and follow the links to RFCs for more complete details.Degradable
F
21

Using the idea of plain text eml files, I came up with this: http://jsfiddle.net/CalvT/un3hapej/

This is an edit of something I found - to create a .txt file then download it. As .eml files are practically .txt files, I figured this would work. And it does. I've left the textarea with the sample email in so you can easily test. When you click on create file, it then gives you a download link to download your .eml file. The only hurdle I can see is making the browser open the .eml file after it has been downloaded.

EDIT: And thinking about it, as you have access to the client machines, you could set the browser to always open files of that type. For instance in Chrome, you can click on the arrow beside the download and select always open files of this type.

Here's the code

HTML:

(function () {
var textFile = null,
  makeTextFile = function (text) {
    var data = new Blob([text], {type: 'text/plain'});

    if (textFile !== null) {
      window.URL.revokeObjectURL(textFile);
    }

    textFile = window.URL.createObjectURL(data);

    return textFile;
  };


  var create = document.getElementById('create'),
    textbox = document.getElementById('textbox');

  create.addEventListener('click', function () {
    var link = document.getElementById('downloadlink');
    link.href = makeTextFile(textbox.value);
    link.style.display = 'block';
  }, false);
})();
<textarea id="textbox" style="width: 300px; height: 200px;">
To: User <[email protected]>
Subject: Subject
X-Unsent: 1
Content-Type: text/html

<html>
<body>
Test message
</body>
</html>
  
</textarea>

<button id="create">Create file</button>
  
<a download="message.eml" id="downloadlink" style="display: none">Download</a>
Femur answered 15/1, 2015 at 19:46 Comment(6)
I am planning to develop this futher as it interests meFemur
Did you discovered how to add attachments via eml file?Ciera
Is it possible to open the eml file in outlook directly without downloading it in the browser ?Bunchy
I have a similar requirement and have followed this approach,however I have base64 encoded images in the email content.When the eml is generated the size of the image reduces. Also the fiddler does not work with Microsoft Edge Browser version Version 90.0.818.56.Below is the link created for same -> #67523617Doom
@Doom the fiddle works for me on Edge 90.0.818.62, so maybe your issue is a local one?Femur
@Femur I am not sure on that, though it works on other Edge versions that I could test.However with base64 encoded image embedded in html,this has issues rendering the image. jsfiddle.net/AnitaSS/g7jnvuab/1Doom
E
13

Nobody seems to have answered the attachment question, so here's my solution: create the EML as a multipart/mixed message.

Content-Type: multipart/mixed; boundary=--boundary_text_string

With this, you can have multiple parts in your email. Multiple parts let you add attachments, like this.

Content-Type: application/octet-stream; name=demo.pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment

Start with your email headers, then add your boundary, then the part contents (newline locations are very important, clients won't parse your file correctly otherwise). You can add multiple parts. Below is an example. Note that the last boundary is different from the others (2 dashes at the end).

To: Demo-Recipient <[email protected]>
Subject: EML with attachments
X-Unsent: 1
Content-Type: multipart/mixed; boundary=--boundary_text_string

----boundary_text_string
Content-Type: text/html; charset=UTF-8

<html>
<body>
<p>Example</p>
</body>
</html>

----boundary_text_string
Content-Type: application/octet-stream; name=demo.txt
Content-Transfer-Encoding: base64
Content-Disposition: attachment
ZXhhbXBsZQ==

----boundary_text_string
Content-Type: application/octet-stream; name=demo.log
Content-Transfer-Encoding: base64
Content-Disposition: attachment
ZXhhbXBsZQ==

----boundary_text_string--

This gives you a eml file with two attachments. See RFC 1371 if you want to know more specifics on how this works.

Espinosa answered 1/10, 2018 at 10:21 Comment(0)
I
3

I had encoding problem when creating an .eml file with non-english characters and then opening it in Outlook. The problem was that I put the "charset=" to the wrong place and did not put the quotes (") around the encoding. The solution:

function createShiftReportEmail() {
    const title = "Shift Összefoglaló";
    const body = "ÁÉŐÚŰÓÜÖÍűáéúőóöí";

    const emlContent = new Blob([`data:message/rfc822 eml,\nSubject: ${title}\nX-Unsent: 1\nContent-Type: text/plain;charset="utf-8"\n\n${body}`]);

    if (!document.querySelector('#downloadEmail')) {
        document.body.insertAdjacentHTML('beforeend', '<a id="downloadEmail" download="ShiftReport.eml" style="display: none">Download</a>');
    }
    const downloadBtn = document.querySelector('#downloadEmail');
    downloadBtn.href = URL.createObjectURL(emlContent);
    downloadBtn.click();
}

Edit: Turns out quotes (") are not even necessary. Only the placement was wrong for me.

Izanami answered 7/8, 2020 at 9:27 Comment(0)
T
1

JS libraries to make a life simpler (no need to invent a wheel):

  • compose EML file: nodemailer/lib/mail-composer
  • parse EML file: mailparser
  • parse MSG file: @kenjiuno/msgreader
Titleholder answered 22/6, 2023 at 7:37 Comment(1)
thanks, that is really helpful. It would be very nice however to have an example of creating EML file with nodemailer/lib/mail-composerRajewski
W
0

After try korhojoa answer, it's not working and need some adjustments:

To: Demo-Recipient <[email protected]>
Subject: EML with attachments
X-Unsent: 1
Content-Type: multipart/mixed; boundary=--boundary_text_string

----boundary_text_string
Content-Type: text/html; charset=UTF-8

<html>
<body>
<p>Example</p>
</body>
</html>

----boundary_text_string
Content-Type: application/octet-stream; name=demo.txt
Content-Transfer-Encoding: base64
Content-Disposition: attachment

ZXhhbXBsZQ==

----boundary_text_string
Content-Type: application/octet-stream; name=demo.log
Content-Transfer-Encoding: base64
Content-Disposition: attachment

ZXhhbXBsZQ==

----boundary_text_string--
Warplane answered 23/5, 2023 at 2:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.