1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2// See LICENSE.txt for license information. 3 4package mail 5 6import ( 7 "bytes" 8 "encoding/json" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "net/http" 13 "os" 14 "strings" 15 "time" 16) 17 18const ( 19 InbucketAPI = "/api/v1/mailbox/" 20) 21 22// OutputJSONHeader holds the received Header to test sending emails (inbucket) 23type 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) 32type 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 50func ParseEmail(email string) string { 51 pos := strings.Index(email, "@") 52 parsedEmail := email[0:pos] 53 return parsedEmail 54} 55 56func 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 91func 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 126func 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 138func 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 159func 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 177func 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} 190