github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/services/mailservice/inbucket.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package mailservice
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"net/http"
    13  	"os"
    14  	"strings"
    15  	"time"
    16  )
    17  
    18  const (
    19  	InbucketAPI = "/api/v1/mailbox/"
    20  )
    21  
    22  // OutputJSONHeader holds the received Header to test sending emails (inbucket)
    23  type JSONMessageHeaderInbucket []struct {
    24  	Mailbox             string
    25  	ID                  string `json:"Id"`
    26  	From, Subject, Date string
    27  	To                  []string
    28  	Size                int
    29  }
    30  
    31  // OutputJSONMessage holds the received Message fto test sending emails (inbucket)
    32  type JSONMessageInbucket struct {
    33  	Mailbox             string
    34  	ID                  string `json:"Id"`
    35  	From, Subject, Date string
    36  	Size                int
    37  	Header              map[string][]string
    38  	Body                struct {
    39  		Text string
    40  		HTML string `json:"Html"`
    41  	}
    42  	Attachments []struct {
    43  		Filename     string
    44  		ContentType  string `json:"content-type"`
    45  		DownloadLink string `json:"download-link"`
    46  		Bytes        []byte `json:"-"`
    47  	}
    48  }
    49  
    50  func ParseEmail(email string) string {
    51  	pos := strings.Index(email, "@")
    52  	parsedEmail := email[0:pos]
    53  	return parsedEmail
    54  }
    55  
    56  func GetMailBox(email string) (results JSONMessageHeaderInbucket, err error) {
    57  
    58  	parsedEmail := ParseEmail(email)
    59  
    60  	url := fmt.Sprintf("%s%s%s", getInbucketHost(), InbucketAPI, parsedEmail)
    61  	resp, err := http.Get(url)
    62  
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	defer func() {
    68  		io.Copy(ioutil.Discard, resp.Body)
    69  		resp.Body.Close()
    70  	}()
    71  
    72  	if resp.Body == nil {
    73  		return nil, fmt.Errorf("No Mailbox")
    74  	}
    75  
    76  	var record JSONMessageHeaderInbucket
    77  	err = json.NewDecoder(resp.Body).Decode(&record)
    78  	switch {
    79  	case err == io.EOF:
    80  		return nil, fmt.Errorf("Error: %s", err)
    81  	case err != nil:
    82  		return nil, fmt.Errorf("Error: %s", err)
    83  	}
    84  	if len(record) == 0 {
    85  		return nil, fmt.Errorf("No mailbox")
    86  	}
    87  
    88  	return record, nil
    89  }
    90  
    91  func GetMessageFromMailbox(email, id string) (JSONMessageInbucket, error) {
    92  	parsedEmail := ParseEmail(email)
    93  
    94  	var record JSONMessageInbucket
    95  
    96  	url := fmt.Sprintf("%s%s%s/%s", getInbucketHost(), InbucketAPI, parsedEmail, id)
    97  	emailResponse, err := http.Get(url)
    98  	if err != nil {
    99  		return record, err
   100  	}
   101  	defer func() {
   102  		io.Copy(ioutil.Discard, emailResponse.Body)
   103  		emailResponse.Body.Close()
   104  	}()
   105  
   106  	if err = json.NewDecoder(emailResponse.Body).Decode(&record); err != nil {
   107  		return record, err
   108  	}
   109  
   110  	// download attachments
   111  	if record.Attachments != nil && len(record.Attachments) > 0 {
   112  		for i := range record.Attachments {
   113  			var bytes []byte
   114  			bytes, err = downloadAttachment(record.Attachments[i].DownloadLink)
   115  			if err != nil {
   116  				return record, err
   117  			}
   118  			record.Attachments[i].Bytes = make([]byte, len(bytes))
   119  			copy(record.Attachments[i].Bytes, bytes)
   120  		}
   121  	}
   122  
   123  	return record, err
   124  }
   125  
   126  func downloadAttachment(url string) ([]byte, error) {
   127  	attachmentResponse, err := http.Get(url)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	defer attachmentResponse.Body.Close()
   132  
   133  	buf := new(bytes.Buffer)
   134  	io.Copy(buf, attachmentResponse.Body)
   135  	return buf.Bytes(), nil
   136  }
   137  
   138  func DeleteMailBox(email string) (err error) {
   139  
   140  	parsedEmail := ParseEmail(email)
   141  
   142  	url := fmt.Sprintf("%s%s%s", getInbucketHost(), InbucketAPI, parsedEmail)
   143  	req, err := http.NewRequest("DELETE", url, nil)
   144  	if err != nil {
   145  		return err
   146  	}
   147  
   148  	client := &http.Client{}
   149  
   150  	resp, err := client.Do(req)
   151  	if err != nil {
   152  		return err
   153  	}
   154  	defer resp.Body.Close()
   155  
   156  	return nil
   157  }
   158  
   159  func RetryInbucket(attempts int, callback func() error) (err error) {
   160  	for i := 0; ; i++ {
   161  		err = callback()
   162  		if err == nil {
   163  			return nil
   164  		}
   165  
   166  		if i >= (attempts - 1) {
   167  			break
   168  		}
   169  
   170  		time.Sleep(5 * time.Second)
   171  
   172  		fmt.Println("retrying...")
   173  	}
   174  	return fmt.Errorf("After %d attempts, last error: %s", attempts, err)
   175  }
   176  
   177  func getInbucketHost() (host string) {
   178  
   179  	inbucket_host := os.Getenv("CI_INBUCKET_HOST")
   180  	if inbucket_host == "" {
   181  		inbucket_host = "localhost"
   182  	}
   183  
   184  	inbucket_port := os.Getenv("CI_INBUCKET_PORT")
   185  	if inbucket_port == "" {
   186  		inbucket_port = "10080"
   187  	}
   188  	return fmt.Sprintf("http://%s:%s", inbucket_host, inbucket_port)
   189  }