Skip to main content

Writing a json to smtp email proxy in go (golang) json2smtp

I wrote a json2smtp proxy server that can be self hosted in Go (golang)


See here:

https://www.c2kb.com/json2smtp

https://github.com/caviv/json2smtp

 

The reason why I needed to write an email proxy was because I was called to do some maintenance on an old legacy system. This system was running on Windows Server 2012, with php version 5.5.6 and Apache 2.4. Very old versions of software. The system was sending emails using the php smtp package and old libssl.dll which supports only TLSv1.0. The smtp service they were using (AWS SES Simple Email Service) has recently dropped the support for SMTP connection via TLS version 1.0. Now in order to support TLS v1.2 for emails on smtp I have to upgrade the whole system. Windows version, php version, Apache version and more - this would have taken me a very long time with many obstacles on the way.



The solution I have chosen was to write this proxy, so calls from the php to send email will be sent as JSON object with attachments to the json2smtp proxy and from there will be sent to the smtp server using TLS 1.2

I have checked some other options that were recommended by Chat-GPT and Bard. But all of them were actually much more complicated to implement than writing my own solution which took me less than a few hours to code. If you know other similar tools and services please let me know.

Here are the tools that did not work for me:
MailSlurp is a cloud-based email proxy that allows you to receive emails in JSON format. It also provides a number of other features, such as the ability to create and manage email addresses, send emails, and track email activity. | This is an online service that costs money.
SMTP2GO is a cloud-based email service that provides a variety of features, including email proxying. It allows you to receive emails in JSON format and send emails through its own SMTP servers.  | This is an online service that costs money.
Mailgun is another cloud-based email service that provides email proxying. It allows you to receive emails in JSON format and send emails through its own SMTP servers.   | This is an online service that costs money.
SendGrid is a cloud-based email service that provides email proxying. It allows you to receive emails in JSON format and send emails through its own SMTP servers.   | This is an online service that costs money.

In addition to these cloud-based services, there are also a number of self-hosted email proxy tools that can be used. Some of these tools include:
Postfix is a popular open-source mail server that can be used as an email proxy. It can be configured to receive emails in JSON format and send emails through its own SMTP servers. | might be ok but very hard to configure.
Exim is another popular open-source mail server that can be used as an email proxy. It can be configured to receive emails in JSON format and send emails through its own SMTP servers.  | might be ok but very hard to configure.
Mailcow Dockerized is a Docker image that contains a number of email server components, including Postfix, Dovecot, and MySQL. It can be configured to receive emails in JSON format and send emails through its own SMTP servers.   | Couldn't make it work

An email proxy: input: json, output: smtp call

For a legacy project I needed to have a proxy email that reads json input and execute a smtp calls in order to send emails. So I created a small proxy for emails in go (golang)
See the code on github: https://github.com/caviv/json2smtp

Download json2smtp binaries executables

Ubuntu linux: json2smtp
Windows amd64: json2smtp-amd64.exe

How it works:

Simple calling diagram:
Simple architecture of calling the json2smtp email proxy server with json and smtp calls

The json struct object

Simple object:

curl -X POST \
 -H "Content-Type: application/json" \
 -d '{ \
"from": "john doe <john@example.com&rt;", \
"to": ["kermit@muppets.com", "oneperson@example.com"], \
"cc": ["email1@example.com"], \
"bcc": ["secret@example.com"], \
"subject": "email subject line", \
"message": "message body in text/html to be sent", \
"attachments": {"filename.pdf": "base64 file encoded", 
                "anotherfilename.txt": "base64 file encoded"}, \
 }' \
 http://localhost:8080/
		

Full object with smtp data:

curl -X POST \
 -H "Content-Type: application/json" \
 -d '{ \
"from": "john doe <john@example.com&rt;", \
"to": ["kermit@muppets.com", "oneperson@ex", \
"to": ["kermit@muppets.com", "oneperson@example.com"], \
"cc": ["email1@example.com"], \
"bcc": ["secret@example.com"], \
"subject": "email subject line", \
"message": "message body in text/html to be sent", \
"attachments": {"filename.pdf": "base64 file encoded", 
                "anotherfilename.txt": "base64 file encoded"}, \
"smtphost": "smtp.example.com - optional parameter", \
"smtpport": 587 - optional paramater, \
"smtpuser": "username - optional parameter", \
"smtppassword": "password - optional parameter" \
 }' \
 http://localhost:8080/
		

Attachments

In order to send attachments with your json email struct you need to construct an object of base64 encoded string of your binary file.

How to install email proxy server:

Download the code and run it

git clone https://github.com/caviv/json2smtp.git
go run ./
go run ./ --help
	

Build and compile

Download the code compile it and run with help command

git clone https://github.com/caviv/json2smtp.git
go build ./
./json2smtp --help
		

Execute smtp2json emal proxy and samples

Command line help:

json2smtp utility https://www.c2kb.com/json2smtp v1.0.1 2023-11-13
Get json input and calls smtp - function as a json to smtp proxy
Options:
  -port int
    	the port to listen on (default 8080)
  -smtphost string
    	smtp host, e.g. smtp.example.com
  -smtpoverride
    	true - allows to pass smtp parameters in the json call,
    	       false will always use the config smtp data (default true)
  -smtppassword string
    	password for the smtp user
  -smtpport int
    	the port to listen on (default 587)
  -smtpuser string
    	username for the smtp
		

Example:

json2smtp --port=8200 --smtphost='smtp.example.com' 
          --smtpport=587 --smtpuser='username' 
          --smtppassword='password'
          --smtpoverride=false
	

Run service in the background:

nohup json2smtp --port=8200 --smtphost='smtp.example.com'
                --smtpport=587 --smtpuser='username'
                 --smtppassword='password' >> logfile.log 2>&1 &
	

Simple execute smtp2json service:

In this way the calling client will have to pass the smtp server details in each call because we don't set the smtp default server for the proxy. The default port to listen on is 8080.

json2smtp
		

Recommended architecture to run the service:

Calling json2smtp proxy behind a caddy web server for https / tls

Libraries used

This external libraries are used in the project:

require gopkg.in/mail.v2 v2.3.1
require gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0

Comments

Popular posts from this blog

Using phpword to merge two Mircrosoft Office Word .docx documents

How to combine or embed and insert another .docx file (Microsoft office docx word document) into another one using PHPWord Joining two .docx document using php ( phpword library ) $mainTemplateProcessor = new \PhpOffice\PhpWord\TemplateProcessor("file1"); //$mainTemplateProcessor ->setValue('var_name', $value); $innerTemplateProcessor = new \PhpOffice\PhpWord\TemplateProcessor("file2"); //$innerTemplateProcessor->setValue('var2_name', $value2); // extract internal xml from template that will be merged inside main template $innerXml = $innerTemplateProcessor->gettempDocumentMainPart(); $innerXml = preg_replace('/^[\s\S]*<w:body>(.*)<\/w:body>.*/', '$1', $innerXml); // remove tag containing header, footer, images $innerXml = preg_replace('/<w:sectPr>.*<\/w:sectPr>/', '', $innerXml); // inject internal xml inside main template $mainXml = $mainTemplateProcessor->gettempDocumentMainPart(...

Bypassing the error by "go get" "tls: failed to verify certificate: x509: certificate signed by unknown authority"

When I was trying to download dependencies for my go project in an old Ubuntu machine I was getting this error all the time: "go: gopkg.in/alexcesaro/quotedprintable.v3@v3.0.0-20150716171945-2caba252f4dc: Get "https://proxy.golang.org/gopkg.in/alexcesaro/quotedprintable.v3/@v/v3.0.0-20150716171945-2caba252f4dc.mod": tls: failed to verify certificate: x509: certificate signed by unknown authority" Which the main part of it was go get failing to authenticate: " tls: failed to verify certificate: x509: certificate signed by unknown authority " I tried many things but couldn't make it work until I found the way: export GOINSECURE="proxy.golang.go" This will tell go get to ignore certification validity. Then export GOPROXY=direct This will tell go get to by pass proxy Then git config --global http.sslverify false And only after those I could run again: go get And it worked