Commit 20a9ed21 authored by Tristan Claverie's avatar Tristan Claverie
Browse files

Merge branch 'mails_cleanup' into 'master'

[mails] Cleanup

- Removed unwanted files
- Put testImg in testdata folder
- Removed existing mail adress and conn info
- Removed filesystem management inside the library
- Fixed critical bug in date header

See merge request !20
parents e0439d6a 5a43b874
Pipeline #224 passed with stage
### DFSS - Mails lib ###
This library is designed to wrap the smtp library of go.
## Initiating a connection to a server ##
To start a connection to a server, create a CustomClient via NewCustomClient
This takes :
- A sender (ex : qdauchy@insa-rennes.fr)
- A host (ex : mailhost.insa-rennes.fr)
- A port (ex : 587)
- A user (ex : qdauchy)
- A password
This requires the server to have TLS
## Using the connection ##
The connection that has been created can then be used to send one or several mails
Using Send requires :
- A slice of receivers
- A subject
- A message
- A (possibly empty) slice of extensions
- A (possibly empty) slice of filenames. This slice must be of the same length as the extensions one.
## Closing the connection ##
Finally, close the connection using Close.
## Example ###
Refer to the doc's to see the library in practice
## Testing the library ##
The testing file uses the following variables to set up the tests :
DFSS_TEST_MAIL_SENDER
DFSS_TEST_MAIL_HOST
DFSS_TEST_MAIL_PORT
DFSS_TEST_MAIL_USER
DFSS_TEST_MAIL_PASSWORD
DFSS_TEST_MAIL_RCPT1
DFSS_TEST_MAIL_RCPT2
Modify the header so that the spam score is lower (9.986 is cutting it close)
Document
......@@ -9,11 +9,9 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/smtp"
"net/textproto"
"strings"
"time"
)
......@@ -24,8 +22,6 @@ type CustomClient struct {
client *smtp.Client
}
const rfc2822 = "Fri 18 Dec 2015 10:01:17 -0606" // used to format time to rfc2822. Not accurate but fmt can't see a ,
// NewCustomClient starts up a custom client.
func NewCustomClient(sender, host, port, username, password string) (*CustomClient, error) {
......@@ -57,7 +53,7 @@ func NewCustomClient(sender, host, port, username, password string) (*CustomClie
}
// Send a mail with the custom client. Returns nil on success.
func (c *CustomClient) Send(receivers []string, subject, message string, extensions, filenames []string) error {
func (c *CustomClient) Send(receivers []string, subject, message string, extensions, filenames []string, files [][]byte) error {
// Keep the connection in a local variable for ease of access
connection := c.client
......@@ -81,7 +77,7 @@ func (c *CustomClient) Send(receivers []string, subject, message string, extensi
// Set the message : header, then message encoded in base64, then attachments
var localBuffer bytes.Buffer
if err := createFullMessage(&localBuffer, receiver, c.sender, header, base64Message, extensions, filenames, boundary); err != nil {
if err := createFullMessage(&localBuffer, receiver, c.sender, header, base64Message, extensions, filenames, files, boundary); err != nil {
return err
}
......@@ -122,14 +118,14 @@ func createHeader(sender, subject, boundary string) string {
fmt.Fprintf(&buffer, "MIME-Version: 1.0\r\n")
fmt.Fprintf(&buffer, "Subject: %s\r\n", subject)
// Replace the first space with a comma and a space to conform to rfc2822
fmt.Fprintf(&buffer, "Date: %s%s", strings.Replace(time.Now().UTC().Format(rfc2822), " ", ", ", 1), "\r\n")
fmt.Fprintf(&buffer, "Date: %s%s", time.Now().Format(time.RFC1123Z), "\r\n")
fmt.Fprintf(&buffer, "Content-Type: multipart/mixed; boundary=\"%s\"; charset=\"UTF-8\"\r\n", boundary)
fmt.Fprintf(&buffer, "To: ")
return buffer.String()
}
// Create the full message for a single receiver
func createFullMessage(b io.Writer, receiver, sender, globalHeader, base64Message string, extensions, filenames []string, boundary string) error {
func createFullMessage(b io.Writer, receiver, sender, globalHeader, base64Message string, extensions, filenames []string, files [][]byte, boundary string) error {
fmt.Fprintf(b, "%s%s\r\n", globalHeader, receiver)
writer := multipart.NewWriter(b)
......@@ -142,8 +138,8 @@ func createFullMessage(b io.Writer, receiver, sender, globalHeader, base64Messag
}
// Set attachments. Here for now because the boundaries are wanted unique
for index, value := range filenames {
if err := createAttachment(writer, extensions[index], value); err != nil {
for index, value := range files {
if err := createAttachment(writer, extensions[index], filenames[index], value); err != nil {
return err
}
}
......@@ -155,7 +151,7 @@ func createFullMessage(b io.Writer, receiver, sender, globalHeader, base64Messag
}
// Create an attachment with a certain extension
func createAttachment(writer *multipart.Writer, extension, path string) error {
func createAttachment(writer *multipart.Writer, extension, path string, file []byte) error {
// Create a header
newHeader := make(textproto.MIMEHeader)
newHeader.Add("Content-Type", extension)
......@@ -168,13 +164,7 @@ func createAttachment(writer *multipart.Writer, extension, path string) error {
return err
}
// Write the file to the message
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
fmt.Fprintf(output, base64.StdEncoding.EncodeToString([]byte(data)))
fmt.Fprintf(output, base64.StdEncoding.EncodeToString(file))
return nil
}
......
......@@ -2,6 +2,7 @@ package mails
import (
"fmt"
"io/ioutil"
"os"
"testing"
)
......@@ -35,35 +36,34 @@ func TestMain(m *testing.M) {
}
func TestSingleMail(t *testing.T) {
err = client.Send([]string{rcpt1}, "TestSingleMail", "Gros espoirs!", []string{}, []string{})
err = client.Send([]string{rcpt1}, "TestSingleMail", "Gros espoirs!", []string{}, []string{}, [][]byte{})
if err != nil {
t.Fatal(err)
}
}
func TestDoubleMail(t *testing.T) {
err = client.Send([]string{rcpt1, rcpt2}, "TestDoubleMail", "Gros espoirs!", []string{}, []string{})
err = client.Send([]string{rcpt1, rcpt2}, "TestDoubleMail", "Gros espoirs!", []string{}, []string{}, [][]byte{})
if err != nil {
t.Fatal(err)
}
}
func TestRuneMail(t *testing.T) {
err = client.Send([]string{rcpt1}, "TestRuneMail", "测试", []string{}, []string{})
err = client.Send([]string{rcpt1}, "TestRuneMail", "测试", []string{}, []string{}, [][]byte{})
if err != nil {
t.Fatal(err)
}
}
func TestAttachmentMailText(t *testing.T) {
err = client.Send([]string{rcpt1}, "TestAttachmentMailText", "What would make a good attachment?", []string{"text/plain"}, []string{"mail_test.go"})
func TestAttachmentMailImage(t *testing.T) {
content, err := ioutil.ReadFile("testdata/testImg.gif")
if err != nil {
t.Fatal(err)
}
}
func TestAttachmentMailImage(t *testing.T) {
err = client.Send([]string{rcpt1}, "TestAttachmentMailImage", "What would make a good attachment?", []string{"image/gif"}, []string{"testImg.gif"})
err = client.Send([]string{rcpt1}, "TestAttachmentMailImage", "What would make a good attachment?", []string{"image/gif"}, []string{"testImg.gif"}, [][]byte{content})
if err != nil {
t.Fatal(err)
}
......@@ -72,27 +72,31 @@ func TestAttachmentMailImage(t *testing.T) {
func ExampleCustomClient() {
// Create a connection
client, err := NewCustomClient("qdauchy@insa-rennes.fr", "mailhost.insa-rennes.fr", "587", "qdauchy", "notreallymypass")
client, err := NewCustomClient("sender@mail.com", "mail.server.com", "25", "username", "password")
if err != nil {
fmt.Println(err)
}
// Some reused variables
receiver1 := "lbonniot@insa-rennes.fr"
receiver2 := "qdauchy@insa-rennes.fr"
receiver3 := "tclaverie@insa-rennes.fr"
recipient1 := "first@recipient.com"
recipient2 := "second@recipient.com"
recipient3 := "third@recipient.com"
subject := "Mail example"
message := `Hello, this is a mail example. It's not like the cactus is going
to be jealous or anything...`
// Send a first mail, without attachments
err = client.Send([]string{receiver1, receiver2}, subject, message, []string{}, []string{})
err = client.Send([]string{recipient1, recipient2}, subject, message, []string{}, []string{}, [][]byte{})
if err != nil {
fmt.Println(err)
}
// Just some test data
fileA := []byte{'A'}
fileB := []byte{'B'}
// Send a second mail, with some attachments
err = client.Send([]string{receiver1, receiver3}, subject, message, []string{"text/plain", "image/gif"}, []string{"email.go", "testImg.gif"})
err = client.Send([]string{recipient1, recipient3}, subject, message, []string{"text/plain", "image/gif"}, []string{"email.go", "testdata/testImg.gif"}, [][]byte{fileA, fileB})
if err != nil {
fmt.Println(err)
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment