mirror of
https://github.com/axllent/mailpit.git
synced 2025-08-15 20:13:16 +02:00
Feature: Add support for sending inline attachments via HTTP API (#399)
Optional settings for Attachment ContentID & ContentType
This commit is contained in:
@@ -80,23 +80,33 @@ type SendRequest struct {
|
|||||||
Subject string
|
Subject string
|
||||||
|
|
||||||
// Message body (text)
|
// Message body (text)
|
||||||
// example: This is the text body
|
// example: Mailpit is awesome!
|
||||||
Text string
|
Text string
|
||||||
|
|
||||||
// Message body (HTML)
|
// Message body (HTML)
|
||||||
// example: <p style="font-family: arial">Mailpit is <b>awesome</b>!</p>
|
// example: <div style="text-align:center"><p style="font-family: arial; font-size: 24px;">Mailpit is <b>awesome</b>!</p><p><img src="cid:mailpit-logo" /></p></div>
|
||||||
HTML string
|
HTML string
|
||||||
|
|
||||||
// Attachments
|
// Attachments
|
||||||
Attachments []struct {
|
Attachments []struct {
|
||||||
// Base64-encoded string of the file content
|
// Base64-encoded string of the file content
|
||||||
// required: true
|
// required: true
|
||||||
// example: VGhpcyBpcyBhIHBsYWluIHRleHQgYXR0YWNobWVudA==
|
// example: iVBORw0KGgoAAAANSUhEUgAAAEEAAAA8CAMAAAAOlSdoAAAACXBIWXMAAAHrAAAB6wGM2bZBAAAAS1BMVEVHcEwRfnUkZ2gAt4UsSF8At4UtSV4At4YsSV4At4YsSV8At4YsSV4At4YsSV4sSV4At4YsSV4At4YtSV4At4YsSV4At4YtSV8At4YsUWYNAAAAGHRSTlMAAwoXGiktRE5dbnd7kpOlr7zJ0d3h8PD8PCSRAAACWUlEQVR42pXT4ZaqIBSG4W9rhqQYocG+/ys9Y0Z0Br+x3j8zaxUPewFh65K+7yrIMeIY4MT3wPfEJCidKXEMnLaVkxDiELiMz4WEOAZSFghxBIypCOlKiAMgXfIqTnBgSm8CIQ6BImxEUxEckClVQiHGj4Ba4AQHikAIClwTE9KtIghAhUJwoLkmLnCiAHJLRKgIMsEtVUKbBUIwoAg2C4QgQBE6l4VCnApBgSKYLLApCnCa0+96AEMW2BQcmC+Pr3nfp7o5Exy49gIADcIqUELGfeA+bp93LmAJp8QJoEcN3C7NY3sbVANixMyI0nku20/n5/ZRf3KI2k6JEDWQtxcbdGuAqu3TAXG+/799Oyyas1B1MnMiA+XyxHp9q0PUKGPiRAau1fZbLRZV09wZcT8/gHk8QQAxXn8VgaDqcUmU6O/r28nbVwXAqca2mRNtPAF5+zoP2MeN9Fy4NgC6RfcbgE7XITBRYTtOE3U3C2DVff7pk+PkUxgAbvtnPXJaD6DxulMLwOhPS/M3MQkgg1ZFrIXnmfaZoOfpKiFgzeZD/WuKqQEGrfJYkyWf6vlG3xUgTuscnkNkQsb599q124kdpMUjCa/XARHs1gZymVtGt3wLkiFv8rUgTxitYCex5EVGec0Y9VmoDTFBSQte2TfXGXlf7hbdaUM9Sk7fisEN9qfBBTK+FZcvM9fQSdkl2vj4W2oX/bRogO3XasiNH7R0eW7fgRM834ImTg+Lg6BEnx4vz81rhr+MYPBBQg1v8GndEOrthxaCTxNAOut8WKLGZQl+MPz88Q9tAO/hVuSeqQAAAABJRU5ErkJggg==
|
||||||
Content string
|
Content string
|
||||||
// Filename
|
// Filename
|
||||||
// required: true
|
// required: true
|
||||||
// example: AttachedFile.txt
|
// example: mailpit.png
|
||||||
Filename string
|
Filename string
|
||||||
|
// Optional Content Type for the the attachment.
|
||||||
|
// If this field is not set (or empty) then the content type is automatically detected.
|
||||||
|
// required: false
|
||||||
|
// example: image/png
|
||||||
|
ContentType string
|
||||||
|
// Optional Content-ID (`cid`) for attachment.
|
||||||
|
// If this field is set then the file is attached inline.
|
||||||
|
// required: false
|
||||||
|
// example: mailpit-logo
|
||||||
|
ContentID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mailpit tags
|
// Mailpit tags
|
||||||
@@ -269,9 +279,15 @@ func (d SendRequest) Send(remoteAddr string) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error decoding base64 attachment \"%s\": %s", a.Filename, err.Error())
|
return "", fmt.Errorf("error decoding base64 attachment \"%s\": %s", a.Filename, err.Error())
|
||||||
}
|
}
|
||||||
|
contentType := http.DetectContentType(b)
|
||||||
mimeType := http.DetectContentType(b)
|
if a.ContentType != "" {
|
||||||
msg = msg.AddAttachment(b, mimeType, a.Filename)
|
contentType = a.ContentType
|
||||||
|
}
|
||||||
|
if a.ContentID != "" {
|
||||||
|
msg = msg.AddInline(b, contentType, a.Filename, a.ContentID)
|
||||||
|
} else {
|
||||||
|
msg = msg.AddAttachment(b, contentType, a.Filename)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -243,6 +243,12 @@ func TestAPIv1Send(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"Content": "VGhpcyBpcyBhIHBsYWluIHRleHQgYXR0YWNobWVudA==",
|
"Content": "VGhpcyBpcyBhIHBsYWluIHRleHQgYXR0YWNobWVudA==",
|
||||||
"Filename": "Attached File.txt"
|
"Filename": "Attached File.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Content": "iVBORw0KGgoAAAANSUhEUgAAAEEAAAA8CAMAAAAOlSdoAAAACXBIWXMAAAHrAAAB6wGM2bZBAAAAS1BMVEVHcEwRfnUkZ2gAt4UsSF8At4UtSV4At4YsSV4At4YsSV8At4YsSV4At4YsSV4sSV4At4YsSV4At4YtSV4At4YsSV4At4YtSV8At4YsUWYNAAAAGHRSTlMAAwoXGiktRE5dbnd7kpOlr7zJ0d3h8PD8PCSRAAACWUlEQVR42pXT4ZaqIBSG4W9rhqQYocG+/ys9Y0Z0Br+x3j8zaxUPewFh65K+7yrIMeIY4MT3wPfEJCidKXEMnLaVkxDiELiMz4WEOAZSFghxBIypCOlKiAMgXfIqTnBgSm8CIQ6BImxEUxEckClVQiHGj4Ba4AQHikAIClwTE9KtIghAhUJwoLkmLnCiAHJLRKgIMsEtVUKbBUIwoAg2C4QgQBE6l4VCnApBgSKYLLApCnCa0+96AEMW2BQcmC+Pr3nfp7o5Exy49gIADcIqUELGfeA+bp93LmAJp8QJoEcN3C7NY3sbVANixMyI0nku20/n5/ZRf3KI2k6JEDWQtxcbdGuAqu3TAXG+/799Oyyas1B1MnMiA+XyxHp9q0PUKGPiRAau1fZbLRZV09wZcT8/gHk8QQAxXn8VgaDqcUmU6O/r28nbVwXAqca2mRNtPAF5+zoP2MeN9Fy4NgC6RfcbgE7XITBRYTtOE3U3C2DVff7pk+PkUxgAbvtnPXJaD6DxulMLwOhPS/M3MQkgg1ZFrIXnmfaZoOfpKiFgzeZD/WuKqQEGrfJYkyWf6vlG3xUgTuscnkNkQsb599q124kdpMUjCa/XARHs1gZymVtGt3wLkiFv8rUgTxitYCex5EVGec0Y9VmoDTFBSQte2TfXGXlf7hbdaUM9Sk7fisEN9qfBBTK+FZcvM9fQSdkl2vj4W2oX/bRogO3XasiNH7R0eW7fgRM834ImTg+Lg6BEnx4vz81rhr+MYPBBQg1v8GndEOrthxaCTxNAOut8WKLGZQl+MPz88Q9tAO/hVuSeqQAAAABJRU5ErkJggg==",
|
||||||
|
"Filename": "logo.png",
|
||||||
|
"ContentID": "inline-cid",
|
||||||
|
"ContentType": "overridden/type"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ReplyTo": [
|
"ReplyTo": [
|
||||||
@@ -294,6 +300,10 @@ func TestAPIv1Send(t *testing.T) {
|
|||||||
assertEqual(t, `Tag 1,Tag 2`, strings.Join(msg.Tags, ","), "wrong Tags")
|
assertEqual(t, `Tag 1,Tag 2`, strings.Join(msg.Tags, ","), "wrong Tags")
|
||||||
assertEqual(t, 1, len(msg.Attachments), "wrong Attachment count")
|
assertEqual(t, 1, len(msg.Attachments), "wrong Attachment count")
|
||||||
assertEqual(t, `Attached File.txt`, msg.Attachments[0].FileName, "wrong Attachment name")
|
assertEqual(t, `Attached File.txt`, msg.Attachments[0].FileName, "wrong Attachment name")
|
||||||
|
assertEqual(t, `text/plain`, msg.Attachments[0].ContentType, "wrong Content-Type")
|
||||||
|
assertEqual(t, 1, len(msg.Inline), "wrong inline Attachment count")
|
||||||
|
assertEqual(t, `logo.png`, msg.Inline[0].FileName, "wrong Attachment name")
|
||||||
|
assertEqual(t, `overridden/type`, msg.Inline[0].ContentType, "wrong Content-Type")
|
||||||
|
|
||||||
attachmentBytes, err := clientGet(ts.URL + "/api/v1/message/" + resp.ID + "/part/" + msg.Attachments[0].PartID)
|
attachmentBytes, err := clientGet(ts.URL + "/api/v1/message/" + resp.ID + "/part/" + msg.Attachments[0].PartID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -1634,12 +1634,22 @@
|
|||||||
"Content": {
|
"Content": {
|
||||||
"description": "Base64-encoded string of the file content",
|
"description": "Base64-encoded string of the file content",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "VGhpcyBpcyBhIHBsYWluIHRleHQgYXR0YWNobWVudA=="
|
"example": "iVBORw0KGgoAAAANSUhEUgAAAEEAAAA8CAMAAAAOlSdoAAAACXBIWXMAAAHrAAAB6wGM2bZBAAAAS1BMVEVHcEwRfnUkZ2gAt4UsSF8At4UtSV4At4YsSV4At4YsSV8At4YsSV4At4YsSV4sSV4At4YsSV4At4YtSV4At4YsSV4At4YtSV8At4YsUWYNAAAAGHRSTlMAAwoXGiktRE5dbnd7kpOlr7zJ0d3h8PD8PCSRAAACWUlEQVR42pXT4ZaqIBSG4W9rhqQYocG+/ys9Y0Z0Br+x3j8zaxUPewFh65K+7yrIMeIY4MT3wPfEJCidKXEMnLaVkxDiELiMz4WEOAZSFghxBIypCOlKiAMgXfIqTnBgSm8CIQ6BImxEUxEckClVQiHGj4Ba4AQHikAIClwTE9KtIghAhUJwoLkmLnCiAHJLRKgIMsEtVUKbBUIwoAg2C4QgQBE6l4VCnApBgSKYLLApCnCa0+96AEMW2BQcmC+Pr3nfp7o5Exy49gIADcIqUELGfeA+bp93LmAJp8QJoEcN3C7NY3sbVANixMyI0nku20/n5/ZRf3KI2k6JEDWQtxcbdGuAqu3TAXG+/799Oyyas1B1MnMiA+XyxHp9q0PUKGPiRAau1fZbLRZV09wZcT8/gHk8QQAxXn8VgaDqcUmU6O/r28nbVwXAqca2mRNtPAF5+zoP2MeN9Fy4NgC6RfcbgE7XITBRYTtOE3U3C2DVff7pk+PkUxgAbvtnPXJaD6DxulMLwOhPS/M3MQkgg1ZFrIXnmfaZoOfpKiFgzeZD/WuKqQEGrfJYkyWf6vlG3xUgTuscnkNkQsb599q124kdpMUjCa/XARHs1gZymVtGt3wLkiFv8rUgTxitYCex5EVGec0Y9VmoDTFBSQte2TfXGXlf7hbdaUM9Sk7fisEN9qfBBTK+FZcvM9fQSdkl2vj4W2oX/bRogO3XasiNH7R0eW7fgRM834ImTg+Lg6BEnx4vz81rhr+MYPBBQg1v8GndEOrthxaCTxNAOut8WKLGZQl+MPz88Q9tAO/hVuSeqQAAAABJRU5ErkJggg=="
|
||||||
|
},
|
||||||
|
"ContentID": {
|
||||||
|
"description": "Optional Content-ID (`cid`) for attachment.\nIf this field is set then the file is attached inline.",
|
||||||
|
"type": "string",
|
||||||
|
"example": "mailpit-logo"
|
||||||
|
},
|
||||||
|
"ContentType": {
|
||||||
|
"description": "Optional Content Type for the the attachment.\nIf this field is not set (or empty) then the content type is automatically detected.",
|
||||||
|
"type": "string",
|
||||||
|
"example": "image/png"
|
||||||
},
|
},
|
||||||
"Filename": {
|
"Filename": {
|
||||||
"description": "Filename",
|
"description": "Filename",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "AttachedFile.txt"
|
"example": "mailpit.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1698,7 +1708,7 @@
|
|||||||
"HTML": {
|
"HTML": {
|
||||||
"description": "Message body (HTML)",
|
"description": "Message body (HTML)",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "\u003cp style=\"font-family: arial\"\u003eMailpit is \u003cb\u003eawesome\u003c/b\u003e!\u003c/p\u003e"
|
"example": "\u003cdiv style=\"text-align:center\"\u003e\u003cp style=\"font-family: arial; font-size: 24px;\"\u003eMailpit is \u003cb\u003eawesome\u003c/b\u003e!\u003c/p\u003e\u003cp\u003e\u003cimg src=\"cid:mailpit-logo\" /\u003e\u003c/p\u003e\u003c/div\u003e"
|
||||||
},
|
},
|
||||||
"Headers": {
|
"Headers": {
|
||||||
"description": "Optional headers in {\"key\":\"value\"} format",
|
"description": "Optional headers in {\"key\":\"value\"} format",
|
||||||
@@ -1751,7 +1761,7 @@
|
|||||||
"Text": {
|
"Text": {
|
||||||
"description": "Message body (text)",
|
"description": "Message body (text)",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "This is the text body"
|
"example": "Mailpit is awesome!"
|
||||||
},
|
},
|
||||||
"To": {
|
"To": {
|
||||||
"description": "\"To\" recipients",
|
"description": "\"To\" recipients",
|
||||||
|
Reference in New Issue
Block a user