github.com/gigforks/mattermost-server@v4.9.1-0.20180619094218-800d97fa55d0+incompatible/utils/inbucket.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package utils
     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) (results JSONMessageInbucket, err error) {
    93  
    94  	parsedEmail := ParseEmail(email)
    95  
    96  	var record JSONMessageInbucket
    97  
    98  	url := fmt.Sprintf("%s%s%s/%s", getInbucketHost(), INBUCKET_API, parsedEmail, id)
    99  	emailResponse, err := get(url)
   100  	if err != nil {
   101  		return record, err
   102  	}
   103  	defer emailResponse.Body.Close()
   104  
   105  	err = json.NewDecoder(emailResponse.Body).Decode(&record)
   106  
   107  	// download attachments
   108  	if record.Attachments != nil && len(record.Attachments) > 0 {
   109  		for i := range record.Attachments {
   110  			if bytes, err := downloadAttachment(record.Attachments[i].DownloadLink); err != nil {
   111  				return record, err
   112  			} else {
   113  				record.Attachments[i].Bytes = make([]byte, len(bytes))
   114  				copy(record.Attachments[i].Bytes, bytes)
   115  			}
   116  		}
   117  	}
   118  
   119  	return record, err
   120  }
   121  
   122  func downloadAttachment(url string) ([]byte, error) {
   123  	attachmentResponse, err := get(url)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	defer attachmentResponse.Body.Close()
   128  
   129  	buf := new(bytes.Buffer)
   130  	io.Copy(buf, attachmentResponse.Body)
   131  	return buf.Bytes(), nil
   132  }
   133  
   134  func get(url string) (*http.Response, error) {
   135  	req, err := http.NewRequest("GET", url, nil)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	client := &http.Client{}
   141  	resp, err := client.Do(req)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  
   146  	return resp, nil
   147  }
   148  
   149  func DeleteMailBox(email string) (err error) {
   150  
   151  	parsedEmail := ParseEmail(email)
   152  
   153  	url := fmt.Sprintf("%s%s%s", getInbucketHost(), INBUCKET_API, parsedEmail)
   154  	req, err := http.NewRequest("DELETE", url, nil)
   155  	if err != nil {
   156  		return err
   157  	}
   158  
   159  	client := &http.Client{}
   160  
   161  	resp, err := client.Do(req)
   162  	if err != nil {
   163  		return err
   164  	}
   165  	defer resp.Body.Close()
   166  
   167  	return nil
   168  }
   169  
   170  func RetryInbucket(attempts int, callback func() error) (err error) {
   171  	for i := 0; ; i++ {
   172  		err = callback()
   173  		if err == nil {
   174  			return nil
   175  		}
   176  
   177  		if i >= (attempts - 1) {
   178  			break
   179  		}
   180  
   181  		time.Sleep(5 * time.Second)
   182  
   183  		fmt.Println("retrying...")
   184  	}
   185  	return fmt.Errorf("After %d attempts, last error: %s", attempts, err)
   186  }
   187  
   188  func getInbucketHost() (host string) {
   189  
   190  	inbucket_host := os.Getenv("CI_HOST")
   191  	if inbucket_host == "" {
   192  		inbucket_host = "dockerhost"
   193  	}
   194  
   195  	inbucket_port := os.Getenv("CI_INBUCKET_PORT")
   196  	if inbucket_port == "" {
   197  		inbucket_port = "9000"
   198  	}
   199  	return fmt.Sprintf("http://%s:%s", inbucket_host, inbucket_port)
   200  }