8/15/2019 update:
The original demo file used the TextEncode function to create the email message file. This function becomes excruciatingly slow when the email includes larger attachments; e.g. it takes longer than a minute to encode an email with a 3 MB attachment.
The demo file has been replaced with an updated version which uses the file manipulation script steps to write out the message file to a file in the temp folder and then read it back into a variable as a container value. This performs much better with larger attachments. However please keep in mind that the file script steps are not supported with WebDirect, so if you need this to work with WebDirect, you will need to use the original TextEncode method.
09/11/2019 update:
The demo file has been updated to fix a bug (having to do with line endings) when sending non-MIME emails.
12/06/2022 update:
Updated demo file so that the script runs itself via PSoS for WebDirect and Data API clients. This is needed, because the file manipulation script steps which create the email message file are incompatible with those clients.
4/16/2024 update:
Please see this blog post for a review on why you should send email using APIs instead of SMTP.
HTML Emails
FileMaker 18 added SMB, LDAP(S), and SMTP(S) to the list of protocols supported by the Insert From URL script step. The full list of supported protocols now is HTTP(S), FTP(S), FILE, SMB, LDAP(S), and SMTP(S). This blog post will focus on making use of cURL and the SMTP protocol to send HTML-formatted emails.
Prior to FileMaker 18, plain text emails could be sent using the Send Mail script step. FileMaker 17 introduced the ability to include multiple attachments. Now, fully stylized rich-text emails with attachments can be sent, but the process is not as simple as it was with the Send Mail step. This blog post breaks down much of what you need to know and supplements that with a demo file for some additional hands-on learning.
Insert From URL
To send an HTML email, the Insert From URL script step needs to have the following items specified:
- Target – stores the result of the cURL command
- URL – specifies the SMTP server URL where the cURL command will be directed to
- Verify SSL Certificates – determines whether the SMTP server SSL certificate should be verified
- cURL options – specifies the options used to fine tune the cURL command
URL
The URL specifies the protocol (SMTP or SMTPS), the fully qualified domain name of the SMTP server, and the port.
Here are some examples of SMTP URLs:
- smtp://smtp.mydomain.com:25/
- smtps://internal-smtp.mydomain.com:587/
cURL Options
The cURL options specify additional instructions for delivery of the email. Here are some of the options that you may use, along with some comments for each one:
–mail-from <address> | This is the email address of the person sending the email. Specify the address only; e.g. llopez@email.com. Do not also include the name like this: Liam Lopez <llopez@email.com>. |
–mail-rcpt <address> | Use this option for the “To”, “Cc”, and “Bcc” addresses. Don’t place multiple recipients on a single line. Instead, repeat this option once for each recipient. For example:
--mail-rcpt cturner@email.com --mail-rcpt awright@email.com |
–user <account>:<password> | Not needed if the SMTP server does not require authentication. |
–upload-file <file> | This option tells cURL where to find the message that is to be sent. In FileMaker, we can use a variable name, like $mailFile, in place of <file>. We’ll cover the message format of the mail file in more detail a bit later. |
–trace <trace> | This option causes all information from the command execution to be saved, which can be very helpful for debugging. In FileMaker, we can specify a variable, like $trace, for <trace>. |
–show-error | This option causes the Get(LastExternalErrorDetail) function to return useful troubleshooting information. |
–ssl-reqd | Require SSL/TLS. The SMTP URL should use the “smtps” protocol designation in this case. |
–ssl | Try to use (but do not require) SSL/TLS. |
Message Format
The SMTP URL and cURL options tell cURL where to send the email, to whom, and how, but they do not directly specify what to send. Instead, the cURL options reference a mail file which includes the content of what is to be sent. This mail file, referred to as the message, has to be constructed following particular formatting rules.
The rules can get quite complex, and a big driver of the complexity is the fact that each new email standard aims to be backward-compatible with the older standard that it supersedes. Some examples of this are the rules that require content to use 7-bit US-ASCII characters with each line of text limited to 78 characters or less (more on that later).
In my testing, I’ve found variations in the extent to which some of these rules are enforced. My guess is this is due to differences in how the various SMTP servers and email clients have implemented the standards that define how internet email works, similar to how support for HTML and JavaScript is implemented differently across different web browsers. The lesson from this is that you may get something to work for a particular SMTP server or email client, but if one of those factors later changes, it may end up breaking the functionality.
MIME Formatting
In the simplest case, where the email message consists of only ASCII characters, none of the lines in the message is longer than 998 characters, and the email does not have any attachments, the message can be constructed using just one “part.” In more complex cases, the email message will use Multipurpose Internet Mail Extensions (MIME) formatting to handle different character encodings, to allow for attachments, or to include alternate (e.g. plain text) versions of the email message.
The message will always consist of a header and a body. In the case of MIME multipart messages, the body itself will be split up into multiple parts, each of which will have its own header and body.
Each part in a multipart message will specify a MIME type to indicate the type of content included in that part. Some examples of MIME types include:
- Plain text: text/plain
- HTML text: text/html
- PNG image: image/png
- PDF: application/pdf
- Zip: application/zip
The full list of defined MIME types can be found here.
So that email clients can tell where one part ends and another begins, each part in a multipart message is separated by a boundary which has to be a string of printable 7-bit ASCII characters (codes 32 through 126) with a length of 70 characters or less, and which must not appear in any of the encapsulated parts. Here is an example of a valid boundary: gc0p4Jq0M2Yt08j34c0p.
Each time a boundary is used, it is prefixed with two hyphens. The last boundary is also suffixed with an additional two hyphens.
MIME Parts
There are three kinds of MIME parts, and therefore three kinds of part boundaries.
Alternative: The “alternative” boundary separates alternate versions of the message. For example, there could be a plain text version of the email to accompany the HTML version, so that old-school plain-text-only email clients can display the message correctly.
The other two types of MIME parts have to do with attachments. Attachments can be embedded within the email message, or they can be attached to the email message in such a way so that they have to be saved out of the email before they can be accessed.
Related: The “related” boundary separates embedded attachments from each other and from the email message.
Mixed: The “mixed” boundary separates non-embedded attachments from each other and from the rest of the message.
The various different parts are nested with the mixed parts forming the outer-most portion of the structure and the alternative parts forming the inner-most portion.
At this point, your head is probably spinning with all of the details, so hopefully, this visual explanation will help clarify your understanding:
The main header section can contain fields such as From, To, Cc, Subject, and Date, but note that the To and Cc fields are not used to determine where the message should be delivered. That information is determined from the cURL options (covered above). The analogy is a paper letter that contains the destination address both on the envelope and on the letter itself. The address on the envelope is the one that is used for delivery. The address shown at the top of the letter is included for informational purposes only.
MIME Format Example
Here is an example of a simple, non-MIME formatted message:
From: Liam Lopez <llopez@email.com>
To: Cameron Turner <cturner@email.com>, April Wright <awright@email.com>,
Theodore Hall <thall@email.com>
Cc: Zara Allen <zallen@email.com>
Subject: Test
Date: Wed, 14 May 2019 19:34:21
Content-Type: text/html; charset="utf8"
<html><body>Hello, here is my <b>bold</b> email message.</body></html>
A couple of things to point out:
- The message body is separated from the header section with an empty line.
- Each line should be separated by CRLF (carriage return and line feed) characters.
- Each line should be kept to a length of no more than 78 characters. The technical limit is actually 998 characters, but the recommended limit is 78. Longer lines should be broken out into multiple lines with a whitespace character beginning each new line. This process is called “folding.”
- The message (both the header and the body) must be comprised of 7-bit ASCII characters.
- The Bcc addresses, if there are any, are typically not included in the message header.
For MIME-formatted messages, non-ASCII data can be converted to 7-bit ASCII using an encoding scheme such as “quoted-printable” or base64 (RFC 2045). When encoding content that consists of mostly Latin-based text, the “quoted-printable” encoding is preferable, since it is human-readable. This makes troubleshooting easier. Both of these encoding schemes automatically fold lines at lengths of 76 characters.
Quoted-printable Encoded Text
Here’s an example of what quoted-printable encoded text looks like:
Original:
Congratulations to Luka Modrić 🇭🇷⚽ for winning the Ballon d'Or!
Quoted-printable:
Congratulations to Luka Modri=C4=87 =F0=9F=87=AD=F0=9F=87=B7=E2=9A=BD for w=
inning the Ballon d'Or!
Unfortunately, FileMaker doesn’t provide a native quoted-printable encoding function, so I used base64 encoding in the demo that accompanies this blog post.
Additional MIME Examples
Here are some additional visual guides that show how email messages (both MIME and non-MIME) are put together.
The pilcrow character (¶) is displayed to denote places where an empty line should be inserted.
To simplify things, some of the text is represented using placeholders. This is denoted with angled brackets; e.g. <<EMAIL_MESSAGE_HTML_TEXT>>.
HTML Email Only
The first example is of a simple non-MIME HTML email.
When I tested sending out this kind of email, I was able to include non-ASCII characters, but the standard specifies that only printable 7-bit ASCII characters should be used. This is another example of the point made earlier, which is that different SMTP servers and email clients implement the standards in different ways, including building in support that allows for stretching the rules. However, if you want to ensure that your email implementation will continue to work regardless of what server or client is used, better adhere to the rules defined in the standards.
HTML Email + Attached Files
This second example shows two attachments included along with the HTML email. In this case, the attachments are not embedded within the email message.
The preamble message is there so that non-MIME compliant email readers can have some intelligible message to show to the user. This message can be anything you want. For example:
This is a message in MIME format. If you see this, your mail reader does not support this format.
HTML Email + Embedded Files + Attached Files
The following example adds two additional attachments, but unlike the previous two, these new ones are embedded within the email. This is done by setting the content disposition to “inline”.
Embedding attachments is commonly done with images. When the HTML for the email is constructed, these attachments can be referred to by their content ID, which is defined in the part header. For example, suppose that the content ID for one of the attachments is defined as follows:
Content-ID: <image001.png@01D4FC56.1590DFB0>
Then the image can be referenced inside the HTML email like this:
<img src="cid:image001.png@01D4FC56.1590DFB0">
Plain Text Email + HTML Email + Embedded Files + Attached Files
The last example uses “alternative” boundaries to add a plain text version of the email message.
Using Encoded-Words in Message Headers
The preceding examples describe how a message body can be encoded to account for non-ASCII characters, but what if the message header also contains these unsupported characters?
For instance, the name of a recipient or the subject of the email could contain characters that fall outside of the 7-bit ASCII range. In that case, you can use encoded-words to convert sequences of unsupported text using the following syntax:
=?charset?encoding?encoded-text?=
For example, suppose the email subject consists simply of the following smiley face emoji: 😋
As a base64 encoded-word, the subject message header would appear as:
Subject: =?UTF-8?B?8J+Yiw==?=
In the example above, the character set is specified as “UTF-8”, the encoding is specified as “B” (for base64), and the encoded text is specified as “8J+Yiw==”, which is the base64 equivalent of 😋
The two encoding options are “B” for base64 and “Q” for quoted-printable.
Similarly, the following recipient message header…
To: 老子 <laotzu@email.com>
…could be encoded as follows:
To: =?UTF-8?B?6ICB5a2Q?= <laotzu@email.com>
You can read more about encoded-word syntax in RFC 2047.
Conclusions and Demo File
We now have the ability to send HTML emails with attachments, but the step up in complexity is significant compared to the Send Mail script step.
The accompanying demo file includes a script which does a lot of the heavy lifting for you. The script was written to be portable so that you can copy it into your solution without having to set up any tables or fields. (The script does rely on the “GetMIMEType” and “ErrorMessage” custom functions though, so you will need to copy those before copying the script.)
The demo file supports fully stylized emails which can be achieved through HTML or through FileMaker field rich text formatting (using the GetAsCSS function). Attachments can be designated as embedded (“Inline”) or as regular, non-embedded (“Attachment”).
The demo file does not, however, support alternative MIME parts, which are used to provide alternate (e.g. plain text) versions of the email message. And it does not do any folding or encoding of message headers. So if your message headers (e.g. subject or recipient email addresses) use non-ASCII characters or are longer than 998 characters in length, the email might not get sent out.
If you do not have an SMTP server readily available for testing, you can create a Gmail account and use the Gmail SMTP server. If you have two-factor authentication enabled (and you should), you will need to create an application-specific password. You can follow these instructions to do so.
As a final word, I’d like to thank my colleagues Brian Engert and Marcelo Piñeyro for their assistance with preparing this blog post and the demo file. If you are looking to implement something similar for your FileMaker solution, please contact our team.
References
- Message format for non-MIME emails: https://en.wikipedia.org/wiki/Email#Message_format
- RFC 5322 standard for non-MIME emails: https://tools.ietf.org/html/rfc5322
- Wikipedia article on MIME messages (includes links to the relevant RFC standards): https://en.wikipedia.org/wiki/MIME
- Message header fields: https://www.iana.org/assignments/message-headers/message-headers.xhtml
- Encoded-word syntax (RFP 2047): https://tools.ietf.org/html/rfc2047
- Complete list of MIME types: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types
- An excellent guide to multi-part MIME messages written by Daniel Clark: http://qcode.co.uk/post/70
Really great article Mislave. Thank you for sharing.
Thanks, Mislav – this saves me a lot of research and head-scratching!
Wonderful compilation of knowledge about HTML emails!
Cannot wait to implement it in our solutions.
Hi Mislav,
Thx for the great blog post!
( small errata in figure 5: first “text/html” should be “test/plain” I think… )
Kind regards,
Jan
oops, I now made a typo myself ;-( not “test/plain”, but “text/plain” of-course…
Jan, thank you for the correction. You’re right – that should say “text/plain”. I’ll work on getting that fixed shortly.
I am finding that when sending emails with FileMaker html as fmp protocol hyperlinks that Gmail seems to strip out the hyperlink so that they are not clickable? The links work in ios mail though but not Gmail? Can you confirm the same behavior or if there is a workaround?
For example the View FileMaker link below does not work in Gmail but the other website http link does but both of them work in ios mail:
From: My Name
To: Sales
Subject: HTML Email Test
Content-Type: text/html; charset=”utf8″
Body of <b>email</b> <a href="//$/mydatabase.fmp12?script=FindPOList&$param=list&$po=p60429,p60448,p60449" rel="nofollow">View FileMaker Records</a> <a href="https://www.mywebsite.com" rel="nofollow">My Website</a> qty: <strong>1</strong>
Thank you,
Shawn
Hi Shawn, I haven’t encountered this situation yet. If I have a chance to look into it, I’ll be sure to post back here with my findings.
Shawn,
I looked into this a bit further, and as it turns out, Gmail strips out protocol anchors from all non-http/https links. See https://stackoverflow.com/questions/23575553/ios-deep-linking-is-stripped-out-in-gmail. A possible workaround could be to link to a web page that you create that then redirects the user to the file protocol link. This would open a new browser tab and then open FileMaker.
— Mislav
Something like the following might work. (Courtesy of my colleague Brian Engert.) This will take any parameters passed to the php script and send them on to FileMaker. Save it as a php file – e.g. fmp.php – and host it on a server somewhere.
<html>
<head>
<meta http-equiv="Refresh" content="0; url=fmp://$/mydatabase.fmp12?<?= http_build_query($_GET) ?>" />
</head>
<body>
Opening filemaker
</body>
</html>
Your email would then include a link like this:
https://my.server.com/fmp.php?script=FindPOList&$param=list&$po=p60429,p60448,p60449
Hi,
Thanks a lot for your sharing.
I find twi drawbacks in sending mail using direct smtp instead of email client:
– I do not have a copy in sent folder
– i cannot take advantage from email-client contact auto completion (using fm field as address container)
Hello,
is there a way to upload email to sent folder via IMAP ?
Thanks,
Hi Paolo, I might not be understanding your question correctly, but if you looking to send mail via IMAP, that won’t work. Mail is sent out using SMTP and retrieved using IMAP or POP3. FileMaker’s Insert from URL script step supports using cURL with SMTP but not IMAP or POP3. Hope this helps.
Hi Mislav,
i was not that clear, sorry, I would like to have a copy of the email sent, in the sent mail folder.
Thanks again
up
As I understand it, SMTP is used to send emails only. It doesn’t know about email folders. To have the sent email stored in your Sent folder, you would have to make an IMAP call separate from the SMTP call. But unfortunately IMAP is not a supported FileMaker cURL protocol.
Possible workarounds:
(1) If you are sending email via SMTP using an Exchange server, the email will be added to the Sent folder automatically, so long as you use the username and password for the appropriate user account.
(2) You could make a separate IMAP call using some non-native method (e.g. a plugin) to save the email in the Sent folder – see the IMAP APPEND command.
(3) BCC yourself on the email (but note that the email will be received in your Inbox, not your Sent folder).
REALLY clever solution with encoding the subject with base64! I was all set to come up with some nutty custom function to solve this and am glad I took a closer look!
Thank you,
Jason
I’m glad it was helpful.
Very useful blog and demo file. I have been able to adapt it to our specific needs, and it works flawlessly. However, I have one problem: the body text of our mail messages is the result of several calculations in FM.
Several lines look like this:
some text (Char9) 0.000,00 €
some more text (Char9) 000,00 €
some text (Char9) 0.000,00 €
In the FM text field the TAB position and alignment (right) have been set and appear correctly. When converted to mail however, the TAB settings disappear and we end up with left aligned text without TAB settings. Is there a workaround to achieve this ?
Rudi
Hi Rudi, I’m glad to hear you found the blog and demo file helpful.
My guess is that because the tab positioning and alignment is a setting that is specified at the level of a layout object, it won’t get picked up by the GetAsCSS function which only looks at the rich-text formatting specified directly in the value of the text field. If I’m correct about this, then the only way that you will be able to achieve the exact type of formatting you want is to create the HTML directly (as opposed to relying on FileMaker rich text formatting and the GetAsCSS function).
Thanks for this Mislav, really helpful.
One question, Gmail specific and not directly related to this article, but associated. For an organisation that uses Gmail for its users do you know if there is there a way to set up one app key for all members of that google organisation unit?
That would greatly simplify the management of the authentication.
Thanks
Tim
Hi Tim,
I don’t have experience with G Suite, which is what I think is used to administer Gmail for an organization, but I would be surprised if it would be possible to do what you’re describing.
First, to clarify, I assume you’re asking about creating an application-specific password (which is only used when 2-step verification is enabled). If that’s the case, as I understand it, that password can be used not just to send email but also to access (i.e. read) it. So if there was one password for an organization, that password could be used to access email for all users. I would be surprised if Google allowed this.
Based on this support article (https://support.google.com/a/answer/2537800?hl=en) – see the “View and revoke application-specific passwords” section – the application-specific password is created by users themselves. Admins cannot create or view the password; they can only revoke it.
Thanks Mislav,
found that info myself after posting the question – it doesn’t look possible to do what client would like. Unfortunately the technical level of the users does not suggest that they could manage their own application passwords – particularly when their procedures require passwords being reset every 90 days, and that would require creating new application passwords.
Time they moved off Google!
Thanks again
Tim
Great resource. Thanks!
Hi Mislav,
I’m new to filemaker. I did convert your work to Runtime solution and I get unknowns error when sending email. Is that the limitation on running fm runtime kiosk ?
Thanks!
HL Wong
Hi HL,
Unfortunately, yes. Claris has deprecated FileMaker Pro runtime back when version 14 was released, and a lot of the functions that have been added since then are not supported with runtime.
https://support.claris.com/s/article/FileMaker-Deprecated-Features-and-Operating-Systems-1503693017248?language=en_US
Hi Mislav,
Thanks for a great solution to sending html emails from Filemaker. It works brilliantly after entering my email settings. I am by no means a developer or someone who understands coding. I simply followed the Filemaker step by step tutorials to get our Not For Profit membership database up and running. But what I’m trying to do is simply send html emails to particular people in our database. So the solution is obviously to incorporate something like your solution into our database. Problem is, I don’t know how to do it. I’m sure it’s not that difficult, if you know how.
I’ve literally spent the last week trying all sorts of plugins and various solutions, but I just don’t know enough about Filemaker and coding to even know where to start. I’m not asking you to write a script solution for me, but any suggestions you might have to point me in the right direction would be greatly appreciated.
Thanks,
James.
Hi James,
Try following these steps:
1. Copy the “GetMIMEType” and “ErrorMessage” custom functions from the demo file into your solution.
2. Then copy the “Send Email Using Insert From URL” script into your solution.
3. Create a button or another script that calls the “Send Email Using Insert From URL” script. You will need to pass it a script parameter. If you’re not a developer, constructing the parameter will probably be the toughest thing for you to do. Take a look at the “Send Email” script in the demo file to see an example of how I did it there.
If you get stuck, contact us at info@soliantconsulting.com and ask for me, and I’ll help you along.
Hello,
I use the OVH exchange server and when I try your technique, I always get “Connection failed”.
The parameters are good, it works when I use another technique implemented for several years, but I would like to change and use yours.
Any idea?
Just tried the normal script step “Send Mail” and it works too with the SMTP and with OVH exchange.
We tried to use the terminal to reproduce the error, here is it :
Command :
XXX-MacBook-Pro-2:Desktop XXX$ curl –url ‘smtp://ex2.mail.ovh.net:587’ –mail-from XXX@XXX.XXX –mail-rcpt xxx@XXX.XXX –upload-file email.txt –user xxx@xxx.xxx:XXXXXX –show-error –ssl -k -v
Response/Error :
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0* Trying 193.70.93.53…
* TCP_NODELAY set
* Connected to ex2.mail.ovh.net (193.70.93.53) port 587 (#0)
EHLO email.txt
< 250-ex2.mail.ovh.net Hello [109.132.65.58]
< 250-SIZE 104857600
< 250-PIPELINING
< 250-DSN
< 250-ENHANCEDSTATUSCODES
< 250-STARTTLS
< 250-AUTH GSSAPI NTLM
< 250-8BITMIME
< 250-BINARYMIME
STARTTLS
EHLO email.txt
< 250-ex2.mail.ovh.net Hello [109.132.65.58]
< 250-SIZE 104857600
< 250-PIPELINING
< 250-DSN
< 250-ENHANCEDSTATUSCODES
< 250-AUTH GSSAPI NTLM LOGIN
< 250-8BITMIME
< 250-BINARYMIME
AUTH GSSAPI
< 334 GSSAPI supported
* gss_init_sec_context() failed: No credentials cache file found.
0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, close notify (256):
} [2 bytes data]
curl: (56) Failure when receiving data from the peer
That looks like an authentication error. I would expect something like the line below after authentication.
> VRFY xxx@XXX.XXX
Yeah I know but the credentials are good, I’ve checked it. I’m kinda lost with this error, maybe its an issue from Exchange
Based on a few google searches, it seems that gss_init_sec_context is part of GSSAPI and is used with Kerberos. I’m not familiar with Kerberos, so I’m afraid I won’t be able to help here. From the little that I do know about Kerberos, access to services (like SMTP) is granted based on tickets which are issued upon authentication. So I’m guessing you would somehow need to incorporate the ticket as part of your request to SMTP. But I don’t know how this would be done or if it would even be supported with FileMaker’s implementation of curl.
Hi Mislav, thanks for your wonderful solution to send HTML e-mails. I have used your scriptset in several solutions, and they work very fast and reliable. But now I am lost: after implementing in a new app and new smtp server settings, I keep getting an error 1628 (SSL error).
More specific:
error:1408F10B:SSL routines:ssl3_get_record:wrong version number
Are we missing some curl option to get SSL right? Can we solve this?
Hi Bertus,
Is there a proxy involved? See https://stackoverflow.com/questions/50840101/curl-35-error1408f10bssl-routinesssl3-get-recordwrong-version-number.
Can you post the full curl trace here (making sure to remove or obfuscate any sensitive info first) or email it to me (send to info@soliantconsulting.com and ask to forward to me)?
I checked it: no proxy involved, he states. Did you receive the trace log?
Hope you can help.
Hi Mislav, thank you. I have mail the trace log to the mail address you provided.
Don’t know if there’s a proxy involved. I will check this with the systems administrator.
Hi Bertus,
I received the curl trace. It looks like you set your SMTP Config up to use SSL. I suggest trying to use StartTLS instead. This will cause the initial communication to be unencrypted, and then the client and server will attempt to switch to SSL before any sensitive information is exchanged. Let’s see if that works any better.
Also, I noticed you have –tlsv1.0 included as part of your curl options. It’s been a while since I’ve looked at my code, but I don’t think I specify that anywhere in my script. I suggest dropping that. Doing so will cause the client and server to use the highest level of TLS that they both support.
Good luck!
Mislav,
Thank you for this detailed documentation of a much needed solution. You have repaired FileMaker’s email functionality!
This looks awesome, and may solve many problems with customers trying to use Gmail Via Filemaker but in the Demo file I keep getting (1627) Authentication failed. Any idea’s on why? SMTP Config is smtp.gmail.com Port 465 SSl. (I’ve tried 3 different gmail accounts). Thanks so much if I can get this working it will be a giant benefit to my customers.
Hi Mike, I’m not sure. I haven’t messed around with this in a while. You could try enabling the “allow less secure apps” setting in gmail if you haven’t already. But I think going with the Gmail API would be a better bet as Google has announced they will be disabling basic authentication with SMTP.
Can this be done server side or must it be through a desktop application?
Hi Phil. It should work fine server-side.
Nice work Mislav! You’ve done a great job with this solution.
Just FYI, the users asking why they can’t get it to work with their Gmail accounts have probably not read the final couple of paragraphs after the “get the demo file here” link. For anyone else who said TLDR; – sign into your google account and generate an application password. Use that password when testing with this demo.
Mislav, I can’t tell you how great it is to finally be able to easily send clickable links in an email from FileMaker. Thank you!
I’ve put this to immediate use over the weekend.
I added a “Reply-to:” header very easily as well. This is handy because the client uses a single
account (like “info@”) to send emails to clients, while the reply-to address is that of the company’s project manager for the particular client.
One thing I haven’t figured out is how to use the “from” name and email address, so the email looks like it is
coming from the project manager’s email address, rather than the generic “info@” account.
Is this possible? What and how are these other data points used for when emailing?
Cheers!
Hi Erik,
I’m glad to hear this has been helpful.
To have the email appear to come from a particular project manager, you would need to set just the From header to that project manager’s email address. But my guess is this won’t be possible to do. Most SMTP servers are configured not to allow sending emails from other users’ email addresses, and for good reason – so that those users cannot be spoofed.
That certainly makes sense. I wish the phone companies would figure out this concept.
Hi Mislav,
I have used your script in several apps, and it’s working great. But at this moment I am encountering a strange thing: e-mail is sent to the recipient, but the subject remains empty, and the body of the message is just displaying the content of the generated email.txt file:
Subject: Some meaningful e-mail subject
Date: Thu, 11 Mar 2021 11:55:16
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=”472F7D8B-1229-CD4D-8DA6-8EA4BC504C2A”
This message is in MIME format. This is a message in MIME format.
If you see this, your mail reader does not support this format.
–472F7D8B-1229-CD4D-8DA6-8EA4BC504C2A
Content-Type: multipart/related; boundary=”B3091B0E-9DD0-EE47-AADC-27E63DE495E4″
–B3091B0E-9DD0-EE47-AADC-27E63DE495E4
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: base64
PGJvZHk+DSAgICA8cCBzdHlsZT0iZm9udC1mYW1pbHk6IGhlbHZldGljYSwgQXJpYWw7IGZvbnQt
c2l6ZTogMTYgcHg7IGNvbG9yOiAjNjY1YTU5OyAiPg0NPHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5
OiAnU2Vnb2UgVUknO2ZvbnQtc2l6ZTogMTFweDsiID5HZWFjaHRlIGhlZXIvbWV2cm91dyw8YnIv
Pjxici8+VFdFRURFIEhFUklOTkVSSU5HPGJyLz48YnIvPlVpdCBvbnplIGFkbWluaXN0cmF0aWUg
Ymxpamt0IGRhdCBmYWN0dXVyIDgzNTQgZC5kLiAwNi0wMS0yMDIxIGFkICZldXJvOyAxOTUsNjYg
bm9nIG5pZXQgaXMgdm9sZGFhbiwgb25kYW5rcyBvbnplIGhlcmlubmVyaW5nIHZhbiAwOS0wMi0y
MDIxLiZuYnNwOzxici8+PGJyLz5XaWogdmVyem9la2VuIHUgdnJpZW5kZWxpamsgZ […]
This happens only on the desktop of my customer, which is a Windows machine. And it doesn’t happen very time either. I can’t reproduce the error on my Mac.
Can you give any clue?
Hi Marcel, I don’t see anything wrong there at first glance. Unfortunately I’m quite busy at the moment, so I can’t dig into more deeply. Best of luck.
Hi all, after it working well for some time, yesterday I started getting the same issue. Did anyone sort out what the issues was?
Mislav, thank you for the great tool and explanation.
When sending to multiple recipients, if one of them is a bad email address, the message does not go out to any of them. Instead, the whole process stops at the cURL step and an “ERROR 550: User does not exist” is passed back.
Is it possible to send the email to the other recipients. Since the erroneous email address is passed back, I could write a loop in the script to remove that one and retry. However, I was hoping there was a cURL switch telling it to ignore bad email addresses.
Hi Chris,
By “bad email address”, do you mean a non-existent mailbox or an improperly formatted email address?
Non-existent mailbox:
When I test sending an email to multiple addresses (one of them non-existent), I don’t receive an error, and the email is delivered to the valid addresses. Normally in this type of situation, the email server will also send a rejection email back to the sender.
Invalid address format:
When I send an email to an improperly formatted address, I get FileMaker error 1631 (connection failed) and an smtp error 501 (RCPT failed).
I don’t know why I’m getting different results from you. Maybe your smtp server is configured differently?
Sorry I couldn’t be more help. Good luck with getting this resolved.
Thank you for the file. I got it to work except that the Preview of the email doesn’t work in the web viewer. The mail sent out looks correct though. But the Preview button to show the email composed in the web viewer within the file doesn’t display any images. The mail does. I am on FM19.2.1 on MacOS 11.3.1 THANK YOU!
I have the preview issue as Siegfried on a Mac with 19.4.2
Hi great implementation.
We need implement some thing like that, I have downloaded the sample file, test it and it works, BUT we need it in a WebDirect solution, the solution sent the email but not complete, no body and no attachments.
Do you know if we need make a changes for this work correctly?
Thank You!
Hello Pavel,
The `Send Email Using Insert From URL` script originally used the TextEncode function to create the email message file (which is where the email body and attachments are contained). But that proved to be very slow when large attachments are being sent, so I changed the code to use the file manipulation script steps (like Create Data File for example).
That addressed the performance issue, but unfortunately the file manipulation script steps are not supported with WebDirect. That explains why you’re seeing an empty body and no attachments.
If you need this code to work with WebDirect, you’ll need to update that script accordingly. The change should be pretty straightforward to make — simply disable the file manipulation script steps and re-enable the TextEncode script step. Good luck.
In my case, the time the email was sent was off by two hours. I fixed this by using UTC time instead of the “Get ( CurrentTimestamp )” function on line 53 of the “Send Email Using Insert From URL” script:
Let (
_ts = GetAsTimestamp(Get(CurrentTimeUTCMilliseconds)/1000) ;
Left ( DayName ( _ts ) ; 3 ) & “, ” &
Day ( _ts ) & ” ” &
Left ( MonthName ( _ts ) ; 3 ) & ” ” &
Year ( _ts ) & ” ” &
Right ( 0 & Hour ( _ts ) ; 2 ) & “:” &
Right ( 0 & Minute ( _ts ) ; 2 ) & “:” &
Right ( 0 & Seconds ( _ts ) ; 2 )
)
I encountered a similar issue. The root cause appears to be that the UTC offset is not specified in the $sendTimestamp_forEmailMessage variable. It appears that something downstream assumed the time to be GMT and the email was showing up as sent several hours before it was.
Appending the UTC offset fixed the issue.
Hi Guys,
is there a file-size limit of attached files? We are facing issues with attachment big than 20MB
thx, Markus
Hi Markus, I am not aware of a technical limit, but your SMTP server could impose a size limit.
There is also a performance consideration with sending large attachments. Some of the operations that have to happen include base64 encoding the attachments, concatenating them, creating the email file, etc. FileMaker doesn’t excel (in terms of performance) with these kinds of text parsing/manipulating operations when it comes to larger text sizes. So for this reason, even if you are able to get around the size limit, if you need to send large attachments on a regular basis, you may want to switch to using an API like Mailgun or AWS SES.
Hi,
thank you very much for the Demo. It’s work fine except with HyperText Links. The links are not always clickable. do you have any idea why?
Thank you for your help.
Hi Nadia,
I am not sure. If you haven’t done this already, I suggest double-checking that the links are formatted properly.
Hi,
Thanks for the great article!
I’d very much love to look at the demo file but I can’t see a download link anywhere. What am I missing?
Hi Gary,
Look for the blue-ish “Get the demo file” link in the “Conclusions and Demo File” section.
Hi MISLAV,
Thanks for the smart solution however I can’t get it working on server side. My goal is to use this technique as a scheduled script on a FileMaker cloud server to send out weekly notifications but I can’t get it work for me.
I tested the script on two separate solutions, one hosted on a MAC server and another one hosted on FM cloud. The script works on both solutions when running on FM pro but it spits error 1627 when running the script on server side. Any idea why it fails on the server?
Note: I hard coded the script parameters to make sure on consistency of the parameters data passed to the script for both scenarios.
Hi Siroos,
Sorry, tough to tell based on that information. I assume you’re using the same credentials and SMTP server when testing from the mac server, which means the only difference is the server. 1627 is “authentication failed”, so is there something about the FMC host that would interfere with a request made to the SMTP server?
Yes, I use exactly the same credentials and SMTP server. The script works fine when it runs on FM pro no matter if the file is hosted on a mac server or FMC. And it fails when running on the server.(Again, no matter if the file is hosted on a mac server or FMC. It throughs error 1627 on both servers.)
mac server: macOS High Sierra 10.13.6 (17G14042)
FileMaker server version on mac: 18.0.4.428
FileMaker Cloud Version: 2.19.4.31
It looks like the problem is not specific to a particular server. The authentication fails every time I run the script using PSOS.
Please let me know if you need more info.
Update:
Problem solved!
You’d need to enable two factor authentication for the email account and also create an app password then use this password instead of the Gmail passwords to get it working on the server side.
Thanks so much for the details. Is there a way to add FileMkaere data fields in the body of the html text?
I want to add a date that comes from my clients’ records in the body of the email. I have tried using Variables, Brackets <>, and I just cannot seem to get the data to show up in the email, or the preview.
Any suggestions?
James Toland-Yeh
Hi James,
Yes, you can use fields when constructing the “body” portion of the script parameter. This would work the same way as it would for any calculation expression. For example, you can set the body to something like this:
“The date value is” & MyTable::MyDateField
Hi Mislav,
Thank you very much for making this available – I managed to get it integrated with my solution.
Mislav,
Thanks so much for this helpful blog and file.
It would be great if the demo file had an example of incorporating the Rich Text Editor Add-On to help build the html.
Hi Mislav,
thank you so much for posting this solution.
I am trying to implement this solution. From the Providers web.de and gmx.de I receive a returned mail message.
<<< 554 Transaction failed Reject due to policy restrictions. For
explanation visit
https://web.de/email/senderguidelines
Do you know what I have to change in your script?
Best regards
Kevin
Hi Kevin, I haven’t encountered this, so I don’t have any guidance to give. Based on a quick google search, this error can be a result of a number of issues like typos in the email address, blacklists, incorrect MX entries or DNS records, etc.
Hi Mislav,
great solution, congrats!
I’m working on WebDirect, can you be more specific on how “disable the file manipulation script steps and re-enable the TextEncode script step” ?
Regards, Faber.
Hello Faber,
The script in the demo file used to create the email message file using the TextEncode function. This performed very slowly with large message files, so I switched to using the file manipulation steps to create the message file (create data file, write to data file, close data file, etc.). This performed better but these steps aren’t compatible with WebDirect or Data API clients. So, in the latest version of the demo file, if the client is WebDirect or Data API, the script sends itself to the server (using the Perform Script on Server step) so that it can run under the FMSE process which does support those file manipulation steps.
Good afternoon Mislav,
I’m a database developer for the department of Electrical and Computer Engineering of the University of Waterloo in Ontario, Canada and I work with FileMaker since 2005.
I have been using your code for a long time without any issues and I really thank you for that.
My current server sits in a Windows Server 2016 datacenter and I’m in the process of migrating to Windows Server 2022.
For sending emails I use a university relay server that requires TLS authentication on port 587.
These are the cURL options I use:
List (
$curlOptions_from ;
$curlOptions_recipients ;
“–upload-file $emailMessageFile” ;
“-v” ; // show verbose info
“–user ” & $smtpAccount & “:” & $smtpPassword ;
“–ssl-reqd” ; // require SSL/TLS
“-k” ; // don’t verify SSL certificates
“–trace $trace” ;
“–show-error” ;
)
Microsoft started adding cURL by default in Windows 10, version 1803.
After several attempts I confirm that the code does not work for my particular case if the OS is Windows 10, version 1803 or newer. The authentication fails with error 1627. I tested Windows 10, 11, Windows Server 2019 and 2022.
I really don’t know if the Windows implementation of cURL is the culprit but for me the code works if the only instance of cURL in the machine comes from FileMaker, otherwise do not.
Few interesting facts:
– send mail works
– the code works if there is no encryption (no “–ssl-reqd). I tested this using a different relay server with the same port configuration (587), same username and same password.
– I tried to no avail these options:
–sslv2
–sslv3
–tlsv1.0
–tlsv1.1
–tlsv1.2
–tlsv1.3
–login-options AUTH=LOGIN
– the Windows cURL works fine using:
curl smtp://stmpServer:587 –mail-from senderEmail –mail-rcpt recipientEmail –upload-file email.txt –user “xxxxxx:yyyyyy” -v –login-options AUTH=LOGIN –tlsv1.2 –ssl-reqd –upload-file email.txt
Any suggestion is really appreciated.
Thank you in advance for your time.
Fernando
Hmm, I’m not sure. I’m just back from some time off, so I’m catching up with work and unfortunately don’t have time to devote to this. I suppose I’d start by checking what version of curl is being used in the different environments to see if that sheds any light on the situation. You can check what curl version FileMaker is using by calling Insert from URL with curl options set to “–version”. You’ll need to specify a URL too, but it doesn’t matter which one. Any website will do. Good luck!
Good morning Mislav,
Thank you for taking time to reply.
I both scenarios I’m using the same version of curl. The only difference is the OS with curl preinstalled or not.
I found a workaround that, although not ideal, works.
Instead of using “Insert from URL” I use “Send Event” to invoque curl from the OS directly.
Fernando
Hi,
I’m trying to integrate this into my solution. After much struggle everything I check in the data viewer seems to correspond with when I send the same HTML email using your ‘HTMLemails’ file. Yet, I get error 1631, connection failed.
Any ideas.
Do I just take the $curlOptions to run it manually from the terminal?
Hi Norman, it’s been a while since I’ve delved into the inner workings of this script. For me, it’s worked correctly. I wonder if the issue might be on the SMTP side of things.
To run the cURL command in the terminal, go to the details of one of the cURL logs (click on the button in the portal to the right to get there), and then click on “Get cURL Command and Message File” and follow the instructions from there.
I have a question. Is there any technique to tell the mail server to save a copy ot his email inside of “sent emails” folder ? thanks in advance.
Congrats to this blog.
Congrats Mislav.
Regards from Barcelona.
I don’t think so. SMTP isn’t aware of user inboxes or folders. It just sends out the email.
If you want to see a copy of the email in the ‘sent’ folder, you’ll need to send the email using an API call. (Our advice is to do this even if you didn’t need to keep a copy of the email in the ‘sent’ folder; see https://www.soliantconsulting.com/blog/filemaker-users-emailing-switch-oauth-apis-asap/). For example, if your email service provider is Microsoft, you could use https://learn.microsoft.com/en-us/graph/api/user-sendmail to send the email on behalf of a user (assuming you have the correct permissions set up). This would save the email in the user’s Sent Items folder.