mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 22:00:49 +01:00
Merge pull request #131 from wneessen/v0.4.0-prep
Preparation for the v0.4.0 release:
This commit is contained in:
commit
4100fef083
8 changed files with 20 additions and 14 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -49,6 +49,7 @@ examples/*
|
||||||
.idea/**/dynamic.xml
|
.idea/**/dynamic.xml
|
||||||
.idea/**/uiDesigner.xml
|
.idea/**/uiDesigner.xml
|
||||||
.idea/**/dbnavigator.xml
|
.idea/**/dbnavigator.xml
|
||||||
|
.idea/sonarlint.xml
|
||||||
|
|
||||||
# Gradle
|
# Gradle
|
||||||
.idea/**/gradle.xml
|
.idea/**/gradle.xml
|
||||||
|
|
13
README.md
13
README.md
|
@ -9,7 +9,8 @@ SPDX-License-Identifier: CC0-1.0
|
||||||
[![GoDoc](https://godoc.org/github.com/wneessen/go-mail?status.svg)](https://pkg.go.dev/github.com/wneessen/go-mail)
|
[![GoDoc](https://godoc.org/github.com/wneessen/go-mail?status.svg)](https://pkg.go.dev/github.com/wneessen/go-mail)
|
||||||
[![codecov](https://codecov.io/gh/wneessen/go-mail/branch/main/graph/badge.svg?token=37KWJV03MR)](https://codecov.io/gh/wneessen/go-mail)
|
[![codecov](https://codecov.io/gh/wneessen/go-mail/branch/main/graph/badge.svg?token=37KWJV03MR)](https://codecov.io/gh/wneessen/go-mail)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/wneessen/go-mail)](https://goreportcard.com/report/github.com/wneessen/go-mail)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/wneessen/go-mail)](https://goreportcard.com/report/github.com/wneessen/go-mail)
|
||||||
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go) [![#go-mail on Discord](https://img.shields.io/badge/Discord-%23gomail-blue.svg)](https://discord.gg/dbfQyC4s)
|
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/avelino/awesome-go)
|
||||||
|
[![#go-mail on Discord](https://img.shields.io/badge/Discord-%23go%E2%80%93mail-blue.svg)](https://discord.gg/ysQXkaccXk)
|
||||||
[![REUSE status](https://api.reuse.software/badge/github.com/wneessen/go-mail)](https://api.reuse.software/info/github.com/wneessen/go-mail)
|
[![REUSE status](https://api.reuse.software/badge/github.com/wneessen/go-mail)](https://api.reuse.software/info/github.com/wneessen/go-mail)
|
||||||
<a href="https://ko-fi.com/D1D24V9IX"><img src="https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/5cbed8a4ae2b88347c06c923_BuyMeACoffee_blue.png" height="20" alt="buy ma a coffee"></a>
|
<a href="https://ko-fi.com/D1D24V9IX"><img src="https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/5cbed8a4ae2b88347c06c923_BuyMeACoffee_blue.png" height="20" alt="buy ma a coffee"></a>
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ Some of the features of this library:
|
||||||
* [X] Explicit SSL/TLS support
|
* [X] Explicit SSL/TLS support
|
||||||
* [X] Implicit StartTLS support with different policies
|
* [X] Implicit StartTLS support with different policies
|
||||||
* [X] Makes use of contexts for a better control flow and timeout/cancelation handling
|
* [X] Makes use of contexts for a better control flow and timeout/cancelation handling
|
||||||
* [X] SMTP Auth support (LOGIN, PLAIN, CRAM-MD)
|
* [X] SMTP Auth support (LOGIN, PLAIN, CRAM-MD, XOAUTH2)
|
||||||
* [X] RFC5322 compliant mail address validation
|
* [X] RFC5322 compliant mail address validation
|
||||||
* [X] Support for common mail header field generation (Message-ID, Date, Bulk-Precedence, Priority, etc.)
|
* [X] Support for common mail header field generation (Message-ID, Date, Bulk-Precedence, Priority, etc.)
|
||||||
* [X] Reusing the same SMTP connection to send multiple mails
|
* [X] Reusing the same SMTP connection to send multiple mails
|
||||||
|
@ -53,13 +54,14 @@ Some of the features of this library:
|
||||||
* [X] Output to file support which allows storing mail messages as e. g. `.eml` files to disk to open them in a MUA
|
* [X] Output to file support which allows storing mail messages as e. g. `.eml` files to disk to open them in a MUA
|
||||||
* [X] Debug logging of SMTP traffic
|
* [X] Debug logging of SMTP traffic
|
||||||
* [X] Custom error types for delivery errors
|
* [X] Custom error types for delivery errors
|
||||||
|
* [X] Custom dial-context functions for more control over the connection (proxing, DNS hooking, etc.)
|
||||||
|
|
||||||
go-mail works like a programatic email client and provides lots of methods and functionalities you would consider
|
go-mail works like a programatic email client and provides lots of methods and functionalities you would consider
|
||||||
standard in a MUA.
|
standard in a MUA.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
We aim for good GoDoc documenation in our library which gives you a full API reference. We also provide a more in-depth documentation website at
|
We aim for good GoDoc documenation in our library which gives you a full API reference. We also provide a more in-depth
|
||||||
[go-mail.dev](https://go-mail.dev)
|
documentation website at [go-mail.dev](https://go-mail.dev)
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
|
@ -91,8 +93,11 @@ go-mail was initially authored and developed by [Winni Neessen](https://github.c
|
||||||
|
|
||||||
Big thanks to the following people, for contributing to the go-mail project (either in form of code or by
|
Big thanks to the following people, for contributing to the go-mail project (either in form of code or by
|
||||||
reviewing code, writing documenation or helping to translate the website):
|
reviewing code, writing documenation or helping to translate the website):
|
||||||
|
* [Christian Vette](https://github.com/cvette)
|
||||||
* [Dhia Gharsallaoui](https://github.com/dhia-gharsallaoui)
|
* [Dhia Gharsallaoui](https://github.com/dhia-gharsallaoui)
|
||||||
* [inliquid](https://github.com/inliquid)
|
* [inliquid](https://github.com/inliquid)
|
||||||
* [iwittkau](https://github.com/iwittkau)
|
* [iwittkau](https://github.com/iwittkau)
|
||||||
* [James Elliott](https://github.com/james-d-elliott)
|
* [James Elliott](https://github.com/james-d-elliott)
|
||||||
* [Maria Letta](https://github.com/MariaLetta) (designed the go-mail logo)
|
* [Maria Letta](https://github.com/MariaLetta) (designed the go-mail logo)
|
||||||
|
* [Nicola Murino](https://github.com/drakkan)
|
||||||
|
* [sters](https://github.com/sters)
|
||||||
|
|
2
doc.go
2
doc.go
|
@ -6,4 +6,4 @@
|
||||||
package mail
|
package mail
|
||||||
|
|
||||||
// VERSION is used in the default user agent string
|
// VERSION is used in the default user agent string
|
||||||
const VERSION = "0.3.9"
|
const VERSION = "0.4.0"
|
||||||
|
|
4
msg.go
4
msg.go
|
@ -749,7 +749,7 @@ func (m *Msg) AttachFile(n string, o ...FileOption) {
|
||||||
//
|
//
|
||||||
// CAVEAT: For AttachReader to work it has to read all data of the io.Reader
|
// CAVEAT: For AttachReader to work it has to read all data of the io.Reader
|
||||||
// into memory first, so it can seek through it. Using larger amounts of
|
// into memory first, so it can seek through it. Using larger amounts of
|
||||||
// data on the io.Reader should be avoided. For such, it is recommeded to
|
// data on the io.Reader should be avoided. For such, it is recommended to
|
||||||
// either use AttachFile or AttachReadSeeker instead
|
// either use AttachFile or AttachReadSeeker instead
|
||||||
func (m *Msg) AttachReader(n string, r io.Reader, o ...FileOption) {
|
func (m *Msg) AttachReader(n string, r io.Reader, o ...FileOption) {
|
||||||
f := fileFromReader(n, r)
|
f := fileFromReader(n, r)
|
||||||
|
@ -808,7 +808,7 @@ func (m *Msg) EmbedFile(n string, o ...FileOption) {
|
||||||
//
|
//
|
||||||
// CAVEAT: For EmbedReader to work it has to read all data of the io.Reader
|
// CAVEAT: For EmbedReader to work it has to read all data of the io.Reader
|
||||||
// into memory first, so it can seek through it. Using larger amounts of
|
// into memory first, so it can seek through it. Using larger amounts of
|
||||||
// data on the io.Reader should be avoided. For such, it is recommeded to
|
// data on the io.Reader should be avoided. For such, it is recommended to
|
||||||
// either use EmbedFile or EmbedReadSeeker instead
|
// either use EmbedFile or EmbedReadSeeker instead
|
||||||
func (m *Msg) EmbedReader(n string, r io.Reader, o ...FileOption) {
|
func (m *Msg) EmbedReader(n string, r io.Reader, o ...FileOption) {
|
||||||
f := fileFromReader(n, r)
|
f := fileFromReader(n, r)
|
||||||
|
|
|
@ -2706,7 +2706,7 @@ func TestMsg_AttachEmbedReader_consecutive(t *testing.T) {
|
||||||
ts2 := "Another test string"
|
ts2 := "Another test string"
|
||||||
m := NewMsg()
|
m := NewMsg()
|
||||||
m.AttachReader("attachment.txt", bytes.NewBufferString(ts1))
|
m.AttachReader("attachment.txt", bytes.NewBufferString(ts1))
|
||||||
m.EmbedReader("embeded.txt", bytes.NewBufferString(ts2))
|
m.EmbedReader("embedded.txt", bytes.NewBufferString(ts2))
|
||||||
obuf1 := &bytes.Buffer{}
|
obuf1 := &bytes.Buffer{}
|
||||||
obuf2 := &bytes.Buffer{}
|
obuf2 := &bytes.Buffer{}
|
||||||
_, err := m.WriteTo(obuf1)
|
_, err := m.WriteTo(obuf1)
|
||||||
|
@ -2724,7 +2724,7 @@ func TestMsg_AttachEmbedReader_consecutive(t *testing.T) {
|
||||||
t.Errorf("Expected file attachment string not found in second output buffer")
|
t.Errorf("Expected file attachment string not found in second output buffer")
|
||||||
}
|
}
|
||||||
if !strings.Contains(obuf1.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
if !strings.Contains(obuf1.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
||||||
t.Errorf("Expected embeded file string not found in first output buffer")
|
t.Errorf("Expected embedded file string not found in first output buffer")
|
||||||
}
|
}
|
||||||
if !strings.Contains(obuf2.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
if !strings.Contains(obuf2.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
||||||
t.Errorf("Expected embded file string not found in second output buffer")
|
t.Errorf("Expected embded file string not found in second output buffer")
|
||||||
|
@ -2739,7 +2739,7 @@ func TestMsg_AttachEmbedReadSeeker_consecutive(t *testing.T) {
|
||||||
ts2 := []byte("Another test string")
|
ts2 := []byte("Another test string")
|
||||||
m := NewMsg()
|
m := NewMsg()
|
||||||
m.AttachReadSeeker("attachment.txt", bytes.NewReader(ts1))
|
m.AttachReadSeeker("attachment.txt", bytes.NewReader(ts1))
|
||||||
m.EmbedReadSeeker("embeded.txt", bytes.NewReader(ts2))
|
m.EmbedReadSeeker("embedded.txt", bytes.NewReader(ts2))
|
||||||
obuf1 := &bytes.Buffer{}
|
obuf1 := &bytes.Buffer{}
|
||||||
obuf2 := &bytes.Buffer{}
|
obuf2 := &bytes.Buffer{}
|
||||||
_, err := m.WriteTo(obuf1)
|
_, err := m.WriteTo(obuf1)
|
||||||
|
@ -2757,7 +2757,7 @@ func TestMsg_AttachEmbedReadSeeker_consecutive(t *testing.T) {
|
||||||
t.Errorf("Expected file attachment string not found in second output buffer")
|
t.Errorf("Expected file attachment string not found in second output buffer")
|
||||||
}
|
}
|
||||||
if !strings.Contains(obuf1.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
if !strings.Contains(obuf1.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
||||||
t.Errorf("Expected embeded file string not found in first output buffer")
|
t.Errorf("Expected embedded file string not found in first output buffer")
|
||||||
}
|
}
|
||||||
if !strings.Contains(obuf2.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
if !strings.Contains(obuf2.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
||||||
t.Errorf("Expected embded file string not found in second output buffer")
|
t.Errorf("Expected embded file string not found in second output buffer")
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
buf []byte // contents are the bytes buf[off : len(buf)]
|
buf []byte // contents are the bytes buf[off : len(buf)]
|
||||||
off int // read at &buf[off], write at &buf[len(buf)]
|
off int // read at &buf[off], write at &buf[len(buf)]
|
||||||
err error // initalization error
|
err error // initialization error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returns an error if the Reader err field is not nil
|
// Error returns an error if the Reader err field is not nil
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (a *cramMD5Auth) Start(_ *ServerInfo) (string, []byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backport of: https://github.com/golang/go/commit/58158e990f272774e615c9abd8662bf0198c29aa#diff-772fc9f5d0c86f26e35158fb3e7a71a4967d18b4ec23a5dbb60781ab0babf426
|
// Backport of: https://github.com/golang/go/commit/58158e990f272774e615c9abd8662bf0198c29aa#diff-772fc9f5d0c86f26e35158fb3e7a71a4967d18b4ec23a5dbb60781ab0babf426
|
||||||
// to guarantee backwards compatiblity with Go 1.16-1.18
|
// to guarantee backwards compatibility with Go 1.16-1.18
|
||||||
func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) {
|
func (a *cramMD5Auth) Next(fromServer []byte, more bool) ([]byte, error) {
|
||||||
if more {
|
if more {
|
||||||
d := hmac.New(md5.New, []byte(a.secret))
|
d := hmac.New(md5.New, []byte(a.secret))
|
||||||
|
|
|
@ -22,7 +22,7 @@ import "strings"
|
||||||
// should be the preferred greeting for servers that support it.
|
// should be the preferred greeting for servers that support it.
|
||||||
//
|
//
|
||||||
// Backport of: https://github.com/golang/go/commit/4d8db00641cc9ff4f44de7df9b8c4f4a4f9416ee#diff-4f6f6bdb9891d4dd271f9f31430420a2e44018fe4ee539576faf458bebb3cee4
|
// Backport of: https://github.com/golang/go/commit/4d8db00641cc9ff4f44de7df9b8c4f4a4f9416ee#diff-4f6f6bdb9891d4dd271f9f31430420a2e44018fe4ee539576faf458bebb3cee4
|
||||||
// to guarantee backwards compatiblity with Go 1.16/1.17:w
|
// to guarantee backwards compatibility with Go 1.16/1.17:w
|
||||||
func (c *Client) ehlo() error {
|
func (c *Client) ehlo() error {
|
||||||
_, msg, err := c.cmd(250, "EHLO %s", c.localName)
|
_, msg, err := c.cmd(250, "EHLO %s", c.localName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue