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