[ANN] gomail: a simple interface to send emails

2,247 views
Skip to first unread message

Alexandre Cesaro

unread,
Jun 26, 2014, 12:28:54 PM6/26/14
to golan...@googlegroups.com
Hello, I wrote a new package: gomail. It provides a simple interface to easily write and send emails. It supports attachments, multipart emails and encoding of non-ASCII characters.

Documentation: http://godoc.org/github.com/alexcesaro/mail/gomail

Here is an example:

    package main

    import (
        "log"

        "github.com/alexcesaro/mail/gomail"
    )

    func main() {
        msg := gomail.NewMessage()
        msg.SetAddressHeader("From", "al...@example.com", "Alex")
        msg.SetHeader("To", "b...@example.com")
        msg.AddHeader("To", "co...@example.com")
        msg.SetHeader("Subject", "Hello!")
        msg.SetBody("text/plain", "Hello Bob and Cora!")
        msg.AddAlternative("text/html", "Hello <b>Bob</b> and <i>Cora</i>!")
        if err := msg.Attach("/home/Alex/lolcat.jpg"); err != nil {
            log.Println(err)
            return
        }

        m := gomail.NewMailer("smtp.example.com", "user", "123456", 25)
        if err := m.Send(msg); err != nil { // This will send the email to Bob and Cora
            log.Println(err)
        }
    }

Hope you will enjoy it! Feedback is welcome!

Luke Mauldin

unread,
Jun 26, 2014, 1:31:13 PM6/26/14
to golan...@googlegroups.com, alexandr...@gmail.com
I just want to say THANK YOU for making a package like this.  I have had to do this at a couple of different employers and I always wrote my own custom package (that is not as full-featured) as yours.  Unfortunately, I don't have the opportunity to use Go in my current position but in the future I will definitely use your package for emailing.

Luke 

Alexandre Cesaro

unread,
Jun 27, 2014, 8:39:57 AM6/27/14
to Luke Mauldin, golan...@googlegroups.com
Glad it helps!

Alex Howard

unread,
Jun 30, 2014, 8:35:57 AM6/30/14
to golan...@googlegroups.com, alexandr...@gmail.com
Thanks dude will be using this library in my social network for outgoing email to replace Mailgun API :)

Alexandre Cesaro

unread,
Jul 1, 2014, 6:02:19 AM7/1/14
to Alex Howard, golan...@googlegroups.com
Cool. Please open issues on Github if you find bugs.

Alexandre Cesaro

unread,
Oct 15, 2014, 12:07:42 PM10/15/14
to golan...@googlegroups.com
I just released a new version of Gomail in a new repository: https://github.com/go-gomail/gomail

The new version of Gomail has new features (embedded images, custom SendMail function...), better performances and a simpler API!
It also uses gopkg.in for versioning.

Please note that it is not backward compatible with the old version. However I wrote a small guide to update to the new version: https://github.com/alexcesaro/mail

Any feedback appreciated!

Ed Pelc

unread,
Oct 16, 2014, 9:23:37 PM10/16/14
to golan...@googlegroups.com, alexandr...@gmail.com
Thank  you for this. I haven't spent to much time on email yet(just some basic registration links for development) but formatting everything correctly was a pain. This should save a lot of time later.

Jonas Riedel

unread,
Oct 17, 2014, 2:28:18 PM10/17/14
to golan...@googlegroups.com, alexandr...@gmail.com
Nice thing !

Could you provide a send function where the tls config is exposed so that one is able to set the InsecureSkipVerify flag for StartTLS ?

Thanks,

Jonas

Klaus Post

unread,
Oct 18, 2014, 6:14:25 AM10/18/14
to golan...@googlegroups.com, alexandr...@gmail.com
Very funny - I just ran into the exact same issue yesterday. I tried to copy the send function from smtp to my own package, but I gave up since it relied on to much package stuff.

The issue is that TLS in the golang smtp package always attempts smtp, if the server announces it. If it fails (we have an expired certificate in our case), the client fails, and doesn't attempt a non-TLS  connection.

See http://golang.org/src/pkg/net/smtp/smtp.go?s=1593:1652#L282 for the offending code path.

So yes - if you could make TLS optional that would be great.

/Klaus

PS. Thanks for the nice package, it has been very easy to use!

Alexandre Cesaro

unread,
Oct 20, 2014, 9:58:11 AM10/20/14
to Klaus Post, golan...@googlegroups.com
Ok, this is often requested so I will work on an alternative SendMail function.

Alexandre Cesaro

unread,
Oct 20, 2014, 11:25:06 AM10/20/14
to Klaus Post, golan...@googlegroups.com
Could you try this SendMail function (using gomail.SetSendMail(sendMail)) and tell me if it works when the certificate is invalid?


func sendMail(addr string, a smtp.Auth, from string, to []string, msg []byte) error {
c, err := smtp.Dial(addr)
if err != nil {
return err
}
defer c.Close()
if ok, _ := c.Extension("STARTTLS"); ok {
host, _, _ := net.SplitHostPort(addr)
config := &tls.Config{ServerName: host, InsecureSkipVerify: true}
if err = c.StartTLS(config); err != nil {
return err
}
}
if a != nil {
if ok, _ := c.Extension("AUTH"); ok {
if err = c.Auth(a); err != nil {
return err
}
}
}
if err = c.Mail(from); err != nil {
return err
}
for _, addr := range to {
if err = c.Rcpt(addr); err != nil {
return err
}
}
w, err := c.Data()
if err != nil {
return err
}
_, err = w.Write(msg)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
return c.Quit()
}

Jonas Riedel

unread,
Oct 21, 2014, 2:31:34 AM10/21/14
to golan...@googlegroups.com, klau...@gmail.com, alexandr...@gmail.com
Thanks Alexandre, your "new" sendMail Function Solution works for me. Great work !

Alexandre Cesaro

unread,
Oct 22, 2014, 5:10:35 PM10/22/14
to Jonas Riedel, golan...@googlegroups.com, Klaus Post
I added a new setting to easily skip the TLS verification:

mailer := gomail.NewMailer("smtp.example.com", "user", "123456", 587, gomail.SetTLSConfig(&tls.Config{InsecureSkipVerify: true}))

bra...@smashwords.com

unread,
Oct 22, 2014, 5:39:57 PM10/22/14
to golan...@googlegroups.com, alexandr...@gmail.com
Hello,

Thank you for the very useful package!

I'm curious, do you have any plans to support the format=flowed parameter for text/plain content types?  It seems like a nice way to send plain text.

For reference:


I can look into implementing it, if you like.

Thanks,
  Braden

Alexandre Cesaro

unread,
Oct 23, 2014, 2:55:19 AM10/23/14
to bra...@smashwords.com, golan...@googlegroups.com
I'm not sure: it does not seem to be a very widespread standard and it only works with ASCII-only texts.

However you can open an issue on Github if you want and we will discuss it there.
Message has been deleted

Alexandre Cesaro

unread,
Oct 24, 2014, 6:59:24 PM10/24/14
to Braden Pellett, golan...@googlegroups.com
I can create a new Encoding named "Unencoded", so you can create your messages like that:
msg := gomail.NewMessage(SetEncoding(gomail.Unencoded))

It would set the Content-transfer-encoding header of the body to 8bit (but still encode special characters in headers using quoted-printable).

Is that fine with you?

On Sat, Oct 25, 2014 at 12:18 AM, Braden Pellett <bra...@smashwords.com> wrote:
Hi,

Actually, since I end up formatting the plain text version myself, I can
get pretty close to what I need simply by appending "; format=flowed" to
the contentType string of the Message receiver's SetBody function.
(Though I don't know if that is an ideal way of going about it.)

However, as per RFC3637, I'd like to be able to have the plain/text body
(and only it) not be encoded as quoted printable.  Is there a way to
turn off quoted printable encoding for a given part of the mail message?

Thanks,
  Braden


On Thu, Oct 23, 2014 at 08:58:35AM -0700, bra...@smashwords.com wrote:
> I just know I often see emails in my inbox with it, and those emails end up
> formated well in Mutt. :)
>
> Why do you say it works only for ASCII-only text?  I didn't see that
> mentioned in the RFC, and many of the format=flowed emails I receive are
> UTF-8 (charset=UTF-8).
>
> Anyway, sure, I'll open an issue.
>
> Thanks,
>   Braden

>
> On Wednesday, October 22, 2014 11:55:19 PM UTC-7, Alexandre Cesaro wrote:
> >
> > I'm not sure: it does not seem to be a very widespread standard and it
> > only works with ASCII-only texts.
> >
> > However you can open an issue on Github if you want and we will discuss it
> > there.
> >
> > On Wed, Oct 22, 2014 at 11:39 PM, <bra...@smashwords.com <javascript:>>

Alexandre Cesaro

unread,
Oct 24, 2014, 7:32:47 PM10/24/14
to Braden Pellett, golan...@googlegroups.com
Yes HTML would not be encoded.

I can also add a soft line break after the last space before 78 characters.

On Sat, Oct 25, 2014 at 1:16 AM, Braden Pellett <bra...@smashwords.com> wrote:
Hi,

Yeah, I think that could work.  Though, just to be clear, would that
mean that in a plain and html alternative message, the text/html part
would also not be encoded quoted-printable?  Which I think would mean I
need to be sure to not pass HTML with very long lines (i.e. more than
998 characters before the newline)?

Thanks,
  Braden



On Sat, Oct 25, 2014 at 12:58:28AM +0200, Alexandre Cesaro wrote:
> I can create a new Encoding

> "Unencoded", so you can create your messages like that:
> msg := gomail.NewMessage(SetEncoding(gomail.Unencoded))
>
> It would set the Content-transfer-encoding header of the body to 8bit

Alexandre Cesaro

unread,
Oct 24, 2014, 8:20:03 PM10/24/14
to Braden Pellett, golan...@googlegroups.com
If I add the "Unencoded" setting I want it to be respectful of MIME specifications. That's why I want to insert soft line breaks before 78 characters.
But I don't want to automatically modify the user's inputs (like adding a space before "From" or format=flowed in the header).

Anyway with theses changes you will be able to format your input to be f=f compliant.


On Sat, Oct 25, 2014 at 1:44 AM, Braden Pellett <bra...@smashwords.com> wrote:
Oh, I don't think you need to concern yourself with the wrapping if it
doesn't seem generally applicable... I already am post-processing the
HTML part and have a wrapping method to generate the format=flowed plain
text, so I could just reuse that to prevent long lines in the HTML.

Alternatively, if you are going to do soft line breaks for long lines,
you could perhaps just go all in and provide a format=flowed formatting
option, :)

I just did it like this:

    https://github.com/daBrado/tplmail/blob/master/utils.go#L57-L77

...for a given line at a time, anyway.  Not that this is ideal... I'm
still new to Go..!

Thanks,
  Braden

Alexandre Cesaro

unread,
Oct 25, 2014, 6:35:45 AM10/25/14
to Braden Pellett, golan...@googlegroups.com
I was thinking about a line break after an already existing space. But now I realize that it modifies user's input too.
So I think I will not insert any line breaks in the "unencoded" context.

On Sat, Oct 25, 2014 at 2:28 AM, Braden Pellett <bra...@smashwords.com> wrote:
Hi,

I feel like maybe I am not understanding.  What is a soft line break in
the context of an 'unencoded' setting?

Also, I wasn't able to find reference to MIME wanting a particular line
length, except in the case of the quoted-printable encoding.  At least,
when looking at https://tools.ietf.org/html/rfc2045

Thanks for your help!

  - Braden

peter.di...@gmail.com

unread,
Oct 27, 2014, 9:34:43 AM10/27/14
to golan...@googlegroups.com, alexandr...@gmail.com
Thanks Alexandre - you have no idea how happy I was to discover this at the weekend.
Very much appreciated.

Braden Pellett

unread,
Oct 27, 2014, 1:28:45 PM10/27/14
to Alexandre Cesaro, golan...@googlegroups.com
Okay, makes sense. Thanks!

Alexandre Cesaro

unread,
Oct 28, 2014, 3:42:38 AM10/28/14
to Braden Pellett, golan...@googlegroups.com
@Braden: I pushed the changes: https://github.com/go-gomail/gomail/commit/b4e3113e2dd2e703e92453e15e2161224f12e1fa

@Peter: Thank you for your kind words!

Braden Pellett

unread,
Oct 28, 2014, 6:01:22 PM10/28/14
to Alexandre Cesaro, golan...@googlegroups.com
It is working fine for me. Thanks much!

- Braden

umesh.ve...@gmail.com

unread,
Nov 9, 2014, 5:43:53 PM11/9/14
to golan...@googlegroups.com, alexandr...@gmail.com
Hey Alex I like your work. However I modified this in your package for the absolute path for reading the file. Because on production, the filepath will not necessarily be  /home/developer/.../ instead it might be something else. With this modification, I can pass in the path to my file from my gopath and not worry about portability.

Just a thought. Thanks!

func OpenFile(filename string) (*File, error) {
//content, err := readFile(filename)
absPath,err1 := filepath.Abs(filename)
if err1 != nil {
return nil, err
}
content, err := readFile(absPath)
if err != nil {
return nil, err
}

f := CreateFile(filepath.Base(absPath), content)

return f, nil

}

On Thursday, June 26, 2014 11:28:54 AM UTC-5, Alexandre Cesaro wrote:

jackf...@gmail.com

unread,
Jan 7, 2015, 8:14:49 PM1/7/15
to golan...@googlegroups.com, alexandr...@gmail.com
Hello, You'll need to change the name of the "internal" package for quoted printable to something else for GO1.4, it seems that internal is now used for something else. Thanks for writing the package, it works great, and thank you for poaching stack overflow and answering my question about this.
 
.

Marçal Juan Llaó

unread,
Jan 11, 2015, 4:13:00 PM1/11/15
to golan...@googlegroups.com, alexandr...@gmail.com, jackf...@gmail.com
Hi, I dont' know how to enable TLS encryption when creating a NewMailer, I'm using this:
mailer := gomail.NewMailer("smtp.office365.com", "f...@bar.com", "password", 587)

I don't see any parameter on tls.Config to add for my use case...

Thanks!

PD: I was using PHP's SwiftMailer and this is the config I'm using: array('hostname' => 'smtp.office365.com', 'username' => 'f...@bar.com', 'password' => '....', 'port' => 587, 'encryption' => 'tls', 'timeout' => 20)

El dijous, 8 gener de 2015 2:14:49 UTC+1, jackf...@gmail.com va escriure:

Alexandre Cesaro

unread,
Jan 12, 2015, 4:03:09 AM1/12/15
to Marçal Juan Llaó, golang-nuts, jackf...@gmail.com
Gomail (like net/smtp.SendMail) automatically use TLS encryption (or more precisely STARTTLS).

Alexandre Cesaro

unread,
Jan 12, 2015, 8:03:24 AM1/12/15
to Marçal Juan Llaó, golang-nuts, jackfranzen
I created an issue on Github and gave an answer there: https://github.com/go-gomail/gomail/issues/16

On Mon, Jan 12, 2015 at 1:13 PM, Marçal Juan Llaó <mar...@gmail.com> wrote:
It throws me this error: "504 5.7.4 Unrecognized authentication type"

With PHP is working fine :/

El Mon Jan 12 2015 at 10:02:40 AM, Alexandre Cesaro (<alexandr...@gmail.com>) va escriure:

Marçal Juan Llaó

unread,
Jan 12, 2015, 11:30:04 AM1/12/15
to Alexandre Cesaro, golang-nuts, jackf...@gmail.com
It throws me this error: "504 5.7.4 Unrecognized authentication type"

With PHP is working fine :/

El Mon Jan 12 2015 at 10:02:40 AM, Alexandre Cesaro (<alexandr...@gmail.com>) va escriure:
Gomail (like net/smtp.SendMail) automatically use TLS encryption (or more precisely STARTTLS).

Alexandre Cesaro

unread,
Apr 21, 2015, 5:52:58 AM4/21/15
to nguyenki...@gmail.com, golang-nuts
Can you show your code?

On Tue, Apr 21, 2015 at 11:42 AM, <nguyenki...@gmail.com> wrote:
Hi friend,
I'm facing this error when using your library:

panic: mail: missing phrase

Can you help? 

nguyenki...@gmail.com

unread,
Apr 21, 2015, 11:16:35 AM4/21/15
to golan...@googlegroups.com, alexandr...@gmail.com

nguyenki...@gmail.com

unread,
Apr 22, 2015, 12:18:02 AM4/22/15
to golan...@googlegroups.com, nguyenki...@gmail.com, alexandr...@gmail.com
The issue is solved, I have a chat with you on google hangout. Thanks for your work!

Vào 16:52:58 UTC+7 Thứ Ba, ngày 21 tháng 4 năm 2015, Alexandre Cesaro đã viết:
Reply all
Reply to author
Forward
0 new messages