SendMail function in Golang

Easy-to-use function to send HTML and plain-text emails in Go

func SendMail(addr, from, subject, body string, to []string) error {
	r := strings.NewReplacer("\r\n", "", "\r", "", "\n", "", "%0a", "", "%0d", "")
	c, err := smtp.Dial(addr)
	if err != nil {
		return err
	}
	defer c.Close()
	if err = c.Mail(r.Replace(from)); err != nil {
		return err
	}
	for i := range to {
		to[i] = r.Replace(to[i])
		if err = c.Rcpt(to[i]); err != nil {
			return err
		}
	}
	w, err := c.Data()
	if err != nil {
		return err
	}
	msg := "To: " + strings.Join(to, ",") + "\r\n" +
		"From: " + from + "\r\n" +
		"Subject: " + subject + "\r\n" +
		"Content-Type: text/html; charset=\"UTF-8\"\r\n" +
		"Content-Transfer-Encoding: base64\r\n" +
		"\r\n" + base64.StdEncoding.EncodeToString([]byte(body))
	_, err = w.Write([]byte(msg))
	if err != nil {
		return err
	}
	err = w.Close()
	if err != nil {
		return err
	}
	return c.Quit()
}

Usage:

SendMail("127.0.0.1:25", (&mail.Address{"from name", "[email protected]"}).String(), "Email Subject", "message body", []string{(&mail.Address{"to name", "[email protected]"}).String()})

Apache 2.4.6 + mod_wsgi + Python 3.6 + Django 2.2.6 on CentOS 7

There are many how-to’s on installing Apache with mod_wsgi, python 3.x and Django, but nothing worked for me, looks like mod_wsgi libraries installed by default with yum use Python 2.x, and I keep getting the following error message:

[Mon Oct 14 09:42:07.713418 2019] [:error] [pid 18066] [remote 10.30.40.31:0] mod_wsgi (pid=18066): Target WSGI script '/usr/local/val/app/app/wsgi.py' cannot be loaded as Python module.
[Mon Oct 14 09:42:07.713497 2019] [:error] [pid 18066] [remote 10.30.40.31:0] mod_wsgi (pid=18066): Exception occurred processing WSGI script '/usr/local/val/app/wsgi.py'.
[Mon Oct 14 09:42:07.713560 2019] [:error] [pid 18066] [remote 10.30.40.31:0] Traceback (most recent call last):
[Mon Oct 14 09:42:07.713596 2019] [:error] [pid 18066] [remote 10.30.40.31:0]   File "/usr/local/val/app/app/wsgi.py", line 12, in <module>
[Mon Oct 14 09:42:07.713701 2019] [:error] [pid 18066] [remote 10.30.40.31:0]     from django.core.wsgi import get_wsgi_application
[Mon Oct 14 09:42:07.713718 2019] [:error] [pid 18066] [remote 10.30.40.31:0]   File "/usr/local/val/venv/lib/python3.6/site-packages/django/__init__.py", line 1, in <module>
[Mon Oct 14 09:42:07.713789 2019] [:error] [pid 18066] [remote 10.30.40.31:0]     from django.utils.version import get_version
[Mon Oct 14 09:42:07.713804 2019] [:error] [pid 18066] [remote 10.30.40.31:0]   File "/usr/local/val/venv/lib/python3.6/site-packages/django/utils/version.py", line 71, in <module>
[Mon Oct 14 09:42:07.713886 2019] [:error] [pid 18066] [remote 10.30.40.31:0]     @functools.lru_cache()
[Mon Oct 14 09:42:07.713914 2019] [:error] [pid 18066] [remote 10.30.40.31:0] AttributeError: 'module' object has no attribute 'lru_cache'

Installing Apache and devel package

$ yum install httpd httpd-devel wget

So, I had to compile mod_wsgi library from sources, which actually helped me to fix the error above with running Django app with wsgi.

Let’s make sure we have Python 3.6 or 3.7 installed or actually it would work with any Python 3 minor version.

$ python3
Python 3.6.8 (default, Aug  7 2019, 17:28:10) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.

If we have Python 3 installed, we need to make sure we got mod_wsgi removed, which was installed by yum.

$ yum remove mod_wsgi

Downloading, compiling and installing a mod_wsgi package by doing this:

$ cd /opt
$ wget https://files.pythonhosted.org/packages/25/d8/1df4ba9c051cd88e02971814f0867274a8ac821baf983b6778dacd6e31f7/mod_wsgi-4.6.8.tar.gz
$ tar -zxvf mod_wsgi-4.6.8.tar.gz
$ cd mod_wsgi-4.6.8
$ ./configure --with-python=/usr/bin/python3.6
$ LD_RUN_PATH=/usr/local/lib make
$ sudo make install

Add a new entry to /etc/ld.so.conf

include ld.so.conf.d/*.conf
include /usr/local/lib

Run:

ldconfig

Make sure mod_wsgi linked properly:

# ldd usr/lib64/httpd/modules/mod_wsgi.so
	linux-vdso.so.1 =>  (0x00007ffd5bdd7000)
	libpython3.6m.so.1.0 => /lib64/libpython3.6m.so.1.0 (0x00007fe5ab02b000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe5aae0f000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007fe5aac0b000)
	libutil.so.1 => /lib64/libutil.so.1 (0x00007fe5aaa08000)
	libm.so.6 => /lib64/libm.so.6 (0x00007fe5aa706000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fe5aa338000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fe5ab78f000)

Install Django:

$ pip3.6 install --upgrade pip
$ pip3.6 install Django

Verify Django installed properly:

$ django-admin version
2.2.6

My httpd configuration file looks like this:

Alias /static /usr/local/val/app/static
<Directory /usr/local/val/app/static>
 Require all granted
</Directory>

<Directory /usr/local/val/app/app>
   <Files wsgi.py>
       Require all granted
   </Files>
</Directory>

WSGIDaemonProcess app python-path=/usr/local/val/app:/usr/local/val/venv/lib/python3.6/site-packages python-home=/usr/local/val/env
WSGIProcessGroup app
WSGIScriptAlias / /usr/local/val/app/app/wsgi.py
WSGIPassAuthorization On

Where app is the name of my django app, and val is directory where app is located.

Before that I created virtual environment by running this:

$ python3 -m venv /usr/local/val/env

Test if everything works correctly, you may probably also want to add your hosts to ALLOWED_HOSTS in your settings.py file and setup static files by specifying the following paths in your settings.py

STATIC_ROOT = '/usr/local/val/app/static/'
STATIC_URL = '/static/'

Let me know if you have any questions

Thanks!