Implement first version of signature collector
This commit is contained in:
parent
2d45c99a89
commit
dccb3ba50b
4 changed files with 283 additions and 22 deletions
10
glide.lock
generated
10
glide.lock
generated
|
|
@ -1,5 +1,5 @@
|
|||
hash: 834f29378b80e2f7486b79420679fb1d854c16f2989574090ba80d322a7b71c5
|
||||
updated: 2018-09-02T14:56:08.452174+02:00
|
||||
hash: 4251e23b87e24d3580705ee49d6354cbd956d2ecc254bd9cb2037d5fd6f34d48
|
||||
updated: 2018-09-04T20:05:07.075614+02:00
|
||||
imports:
|
||||
- name: github.com/Sirupsen/logrus
|
||||
version: 78fa2915c1fa231f62e0438da493688c21ca678e
|
||||
|
|
@ -31,7 +31,7 @@ imports:
|
|||
- rsa
|
||||
- ssh/terminal
|
||||
- name: golang.org/x/sys
|
||||
version: fa5fdf94c78965f1aa8423f0cc50b8b8d728b05a
|
||||
version: 2b024373dcd9800f0cae693839fac6ede8d64a8c
|
||||
subpackages:
|
||||
- unix
|
||||
- windows
|
||||
|
|
@ -43,7 +43,7 @@ imports:
|
|||
- encoding/internal
|
||||
- encoding/internal/identifier
|
||||
- transform
|
||||
- name: mimeparser
|
||||
version: f4de8a5a52ecd93189c785c7d87259ac637e1d7c
|
||||
- name: proton/pmmime
|
||||
version: f64ddc9969090ae55c92712def8289587816dc11
|
||||
repo: git@gitlab.protontech.ch:ProtonMail/go-pm-mime.git
|
||||
testImports: []
|
||||
|
|
|
|||
|
|
@ -3,5 +3,6 @@ import:
|
|||
- package: golang.org/x/crypto
|
||||
version: v1.0.0
|
||||
repo: https://github.com/ProtonMail/crypto.git
|
||||
- package: mimeparser
|
||||
- package: proton/pmmime
|
||||
repo: git@gitlab.protontech.ch:ProtonMail/go-pm-mime.git
|
||||
version: feat/mimevisitor
|
||||
|
|
|
|||
141
mime.go
141
mime.go
|
|
@ -6,10 +6,117 @@ import (
|
|||
"net/textproto"
|
||||
"io/ioutil"
|
||||
"bytes"
|
||||
"mimeparser"
|
||||
"proton/pmmime"
|
||||
"io"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
func parseMIME(mimeBody string) (body *mimeparser.BodyCollector, atts, attHeaders []string, err error) {
|
||||
|
||||
|
||||
func DecodePart(partReader io.Reader, header textproto.MIMEHeader) (decodedPart io.Reader) {
|
||||
decodedPart = pmmime.DecodeContentEncoding(partReader, header.Get("Content-Transfer-Encoding"))
|
||||
if decodedPart == nil {
|
||||
log.Warnf("Unsupported Content-Transfer-Encoding '%v'", header.Get("Content-Transfer-Encoding"))
|
||||
decodedPart = partReader
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ======================== Attachments Collector ==============
|
||||
// Collect contents of all attachment parts and return
|
||||
// them as a string
|
||||
|
||||
type SignatureCollector struct {
|
||||
target pmmime.VisitAcceptor
|
||||
signature string
|
||||
}
|
||||
|
||||
func NewSignatureCollector(targetAccepter pmmime.VisitAcceptor) *SignatureCollector {
|
||||
return &SignatureCollector{
|
||||
target: targetAccepter,
|
||||
}
|
||||
}
|
||||
|
||||
func getMultipartParts(r io.Reader, params map[string]string) (parts []io.Reader, headers []textproto.MIMEHeader, err error) {
|
||||
mr := multipart.NewReader(r, params["boundary"])
|
||||
parts = []io.Reader{}
|
||||
headers = []textproto.MIMEHeader{}
|
||||
var p *multipart.Part
|
||||
for {
|
||||
p, err = mr.NextPart()
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
b, _ := ioutil.ReadAll(p)
|
||||
buffer := bytes.NewBuffer(b)
|
||||
|
||||
parts = append(parts, buffer)
|
||||
headers = append(headers, p.Header)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sc *SignatureCollector) Accept(part io.Reader, header textproto.MIMEHeader, hasPlainSibling bool, isFirst, isLast bool) (err error) {
|
||||
parentMediaType, params, _ := mime.ParseMediaType(header.Get("Content-Type"))
|
||||
if parentMediaType == "multipart/signed" {
|
||||
var multiparts []io.Reader
|
||||
var multipartHeaders []textproto.MIMEHeader
|
||||
if multiparts, multipartHeaders, err = getMultipartParts(part, params); err != nil {
|
||||
return
|
||||
} else {
|
||||
hasPlainChild := false
|
||||
for _, header := range multipartHeaders {
|
||||
mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type"))
|
||||
if mediaType == "text/plain" {
|
||||
hasPlainChild = true
|
||||
}
|
||||
}
|
||||
if len(multiparts) != 2 {
|
||||
// Invalid multipart/signed format just pass along
|
||||
for i, p := range multiparts {
|
||||
if err = sc.target.Accept(p, multipartHeaders[i], hasPlainChild, true, true); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// actual multipart/signed format
|
||||
err = sc.target.Accept(multiparts[0], multipartHeaders[0], hasPlainChild, true, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
partData, _ := ioutil.ReadAll(multiparts[1])
|
||||
decodedPart := pmmime.DecodeContentEncoding(bytes.NewReader(partData), header.Get("Content-Transfer-Encoding"))
|
||||
buffer, err := ioutil.ReadAll(decodedPart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer, err = pmmime.DecodeCharset(buffer, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sc.signature = string(buffer)
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
sc.target.Accept(part, header, hasPlainSibling, isFirst, isLast)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (ac SignatureCollector) GetSignature() string {
|
||||
return ac.signature
|
||||
}
|
||||
|
||||
|
||||
func ParseMIME(mimeBody string) (body *pmmime.BodyCollector, atts, attHeaders []string, err error) {
|
||||
|
||||
mm, err := mail.ReadMessage(strings.NewReader(mimeBody))
|
||||
if err != nil {
|
||||
|
|
@ -19,10 +126,12 @@ func parseMIME(mimeBody string) (body *mimeparser.BodyCollector, atts, attHeader
|
|||
h := textproto.MIMEHeader(mm.Header)
|
||||
mmBodyData, err := ioutil.ReadAll(mm.Body)
|
||||
|
||||
printAccepter := mimeparser.NewMIMEPrinter()
|
||||
bodyCollector := mimeparser.NewBodyCollector(printAccepter)
|
||||
attachmentsCollector := mimeparser.NewAttachmentsCollector(bodyCollector)
|
||||
err = mimeparser.VisitAll(bytes.NewReader(mmBodyData), h, attachmentsCollector)
|
||||
printAccepter := pmmime.NewMIMEPrinter()
|
||||
bodyCollector := pmmime.NewBodyCollector(printAccepter)
|
||||
attachmentsCollector := pmmime.NewAttachmentsCollector(bodyCollector)
|
||||
mimeVisitor := pmmime.NewMimeVisitor(attachmentsCollector)
|
||||
signatureCollector := NewSignatureCollector(mimeVisitor)
|
||||
err = pmmime.VisitAll(bytes.NewReader(mmBodyData), h, signatureCollector)
|
||||
|
||||
body = bodyCollector
|
||||
atts = attachmentsCollector.GetAttachments()
|
||||
|
|
@ -31,7 +140,7 @@ func parseMIME(mimeBody string) (body *mimeparser.BodyCollector, atts, attHeader
|
|||
return
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// define call back interface
|
||||
type MIMECallbacks interface {
|
||||
|
|
@ -42,16 +151,16 @@ type MIMECallbacks interface {
|
|||
}
|
||||
|
||||
func (o *OpenPGP) decryptMIMEMessage(encryptedText string, verifierKey string, privateKeys []byte,
|
||||
passphrase string, callbacks MIMECallbacks, verifyTime int64) (verifier int, err error) {
|
||||
decsignverify, error := o.DecryptMessageVerifyPrivbinkeys(encryptedText, verifierKey, privateKeys, passphrase, verifyTime)
|
||||
if (error != nil) {
|
||||
return 0, error
|
||||
passphrase string, callbacks MIMECallbacks, verifyTime int64) (verifier int, err error) {
|
||||
decsignverify, err := o.DecryptMessageVerifyPrivbinkeys(encryptedText, verifierKey, privateKeys, passphrase, verifyTime)
|
||||
if (err != nil) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
body, attachments, attachmentHeaders, error := parseMIME(decsignverify.Plaintext
|
||||
if (error != nil) {
|
||||
return 0, error
|
||||
})
|
||||
body, attachments, attachmentHeaders, err := parseMIME(decsignverify.Plaintext)
|
||||
if (err != nil) {
|
||||
return 0, err
|
||||
}
|
||||
bodyContent, bodyMimeType := body.GetBody()
|
||||
callbacks.onBody(bodyContent, bodyMimeType)
|
||||
for i := 0; i < len(attachments); i++ {
|
||||
|
|
@ -62,4 +171,4 @@ func (o *OpenPGP) decryptMIMEMessage(encryptedText string, verifierKey string, p
|
|||
// Todo verify the signature included in the attachment
|
||||
|
||||
return verifier, nil
|
||||
}
|
||||
}*/
|
||||
151
mime_test.go
Normal file
151
mime_test.go
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
package pmcrypto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
testMessage :=
|
||||
`Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg=pgp-sha256; boundary="---------------------4a9ea9f4dad3f36079bdb3f1e7b75bd0"; charset=UTF-8
|
||||
X-Spam-Status: No, score=1.2 required=7.0 tests=ALL_TRUSTED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, FREEMAIL_REPLYTO_END_DIGIT,HTML_IMAGE_ONLY_08,HTML_MESSAGE autolearn=no autolearn_force=no version=3.4.0
|
||||
X-Spam-Level: *
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.protonmail.ch
|
||||
|
||||
-----------------------4a9ea9f4dad3f36079bdb3f1e7b75bd0
|
||||
Content-Type: multipart/mixed; boundary="---------------------f0e64db835d0f5c3674df52a164b06bb"
|
||||
|
||||
-----------------------f0e64db835d0f5c3674df52a164b06bb
|
||||
Content-Type: multipart/alternative; boundary="---------------------3ca028eaeffb3ca0fb0dd6461f639c2b"
|
||||
|
||||
-----------------------3ca028eaeffb3ca0fb0dd6461f639c2b
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Type: text/plain;charset=utf-8
|
||||
|
||||
|
||||
|
||||
|
||||
[Screenshot from 2018-02-06 17-13-21.png]
|
||||
|
||||
--=C2=A0
|
||||
Julien Palard
|
||||
https://mdk.fr
|
||||
|
||||
|
||||
-----------------------3ca028eaeffb3ca0fb0dd6461f639c2b
|
||||
Content-Type: multipart/related; boundary="---------------------ce717c368c2d3981c954ad7c46cd7bf2"
|
||||
|
||||
-----------------------ce717c368c2d3981c954ad7c46cd7bf2
|
||||
Content-Type: text/html;charset=utf-8
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
PGRpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2IGNsYXNzPSJwcm90b25tYWls
|
||||
X3NpZ25hdHVyZV9ibG9jayI+PGRpdiBjbGFzcz0icHJvdG9ubWFpbF9zaWduYXR1cmVfYmxvY2st
|
||||
dXNlciI+PGRpdj48aW1nIHNyYz0iY2lkOjQ2MDk4ZTliQHByb3Rvbm1haWwuY29tIiBjbGFzcz0i
|
||||
cHJvdG9uLWVtYmVkZGVkIiBhbHQ9IlNjcmVlbnNob3QgZnJvbSAyMDE4LTAyLTA2IDE3LTEzLTIx
|
||||
LnBuZyI+PGJyPjwvZGl2PjxkaXY+LS0mbmJzcDs8YnI+PC9kaXY+PGRpdj5KdWxpZW4gUGFsYXJk
|
||||
PGJyPjwvZGl2PjxkaXY+PGNvZGUgc3R5bGU9ImZvbnQtZmFtaWx5OidTRk1vbm8tUmVndWxhcics
|
||||
IENvbnNvbGFzLCAnTGliZXJhdGlvbiBNb25vJywgTWVubG8sIENvdXJpZXIsIG1vbm9zcGFjZTtm
|
||||
b250LXNpemU6MTEuODk5OTk5NjE4NTMwMjczcHg7cGFkZGluZzowcHg7bWFyZ2luOjBweDtiYWNr
|
||||
Z3JvdW5kLWNvbG9yOnRyYW5zcGFyZW50O3doaXRlLXNwYWNlOnByZTtib3JkZXI6MHB4O2Rpc3Bs
|
||||
YXk6aW5saW5lO292ZXJmbG93OnZpc2libGU7bGluZS1oZWlnaHQ6aW5oZXJpdDsiPjxhIGhyZWY9
|
||||
Imh0dHBzOi8vbWRrLmZyIj5odHRwczovL21kay5mcjwvYT48L2NvZGU+PGJyPjwvZGl2PjwvZGl2
|
||||
PjxkaXYgY2xhc3M9InByb3Rvbm1haWxfc2lnbmF0dXJlX2Jsb2NrLXByb3RvbiBwcm90b25tYWls
|
||||
X3NpZ25hdHVyZV9ibG9jay1lbXB0eSI+PGJyPjwvZGl2PjwvZGl2PjwvZGl2Pg==
|
||||
-----------------------ce717c368c2d3981c954ad7c46cd7bf2--
|
||||
-----------------------3ca028eaeffb3ca0fb0dd6461f639c2b--
|
||||
-----------------------f0e64db835d0f5c3674df52a164b06bb
|
||||
Content-Type: image/png; filename="Screenshot from 2018-02-06 17-13-21.png"; name="Screenshot from 2018-02-06 17-13-21.png"
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: inline; filename="Screenshot from 2018-02-06 17-13-21.png"; name="Screenshot from 2018-02-06 17-13-21.png"
|
||||
Content-ID: <46098e9b@protonmail.com>
|
||||
|
||||
wsBcBAEBCAAQBQJbjodcCRDdVS3pfakUGgAAlhoH/2jBRjOSx5EdkiyyNcCT
|
||||
4DVm+ACoF1KTWE5fLRuDPvSiD934cFoZShJs32r0Wcj/4W4tVhLYzjjtf6xO
|
||||
Ymqe0p3o4oYxxMXIAd4COrnOPGjeD1ausqT6iUCAadqXoDYfowEg4f0Wd0RK
|
||||
ElsP/OZaDjsNoRE3WeRcHTr5XWZxhEsIMgnW591iaTliYvbysLoQ08i3G53c
|
||||
p6q+IANRznx5rDhMdo+shFvhcI2Zszg6X2WuCMhFtUyrqEN8WlZYXMX8PGPO
|
||||
1kNDRl7B7/r4Ap+FffLpeYw+8rG6lQXGc3RCOAnfMq9X/9Ziqzxr7flYtRJH
|
||||
RIzX2CG47PuGl/uvImFW/Iw=
|
||||
|
||||
-----------------------f0e64db835d0f5c3674df52a164b06bb
|
||||
Content-Type: application/pgp-keys; filename="publickey - kaykeytest3@protonmail.com - 0xE1DADAE3.asc"; name="publickey - kaykeytest3@protonmail.com - 0xE1DADAE3.asc"
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment; filename="publickey - kaykeytest3@protonmail.com - 0xE1DADAE3.asc"; name="publickey - kaykeytest3@protonmail.com - 0xE1DADAE3.asc"
|
||||
|
||||
LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tDQpWZXJzaW9uOiBPcGVuUEdQLmpz
|
||||
IHYzLjEuMg0KQ29tbWVudDogaHR0cHM6Ly9vcGVucGdwanMub3JnDQoNCnhzQk5CRnQ2N2I4QkNB
|
||||
QzBTMlU3VUJ3dnkyUnZqcEpwOHlyMlE0R25oNzk0QjUwVG1TMlViTXJRaEovaQpUWFRTZmJhb21l
|
||||
NkdkcmJhSjlvVW0xY2hhMU5hVlNnWHE0RVB2WWxmSWVVdkt1U0tnTVdxaVMzT2xSdGYKT3JwMVZp
|
||||
dXNpZWtldVczL2JtYUZBbzFLQWZvajBMNlF6cVVIY3ZZNnY1RExoWGV2MWlaUW9TN2lrQk9PCmor
|
||||
Z05lUDJabjVIOXdQTFlxdWlqK0pnWFY4djRRQk5uNU82NUNYRkZIbjl1Mzl1Yng2bDJtY2tqaDVm
|
||||
VQppU1FiUkh2RzhIdG96Y2xIcWV1bjBpanNjZEtoOTBsaENsWHlDcHlkZ2JwT2pjL2dDQ2R3WmVh
|
||||
djNNSG0KZnhsd2VReDhmc0xxZ1h5TlNFd3pyODh0MTFWMFQ4TmRjeFdia1lRNllQN2R4UU10RkU0
|
||||
bWM5akxBQkVCCkFBSE5PU0pyWVhsclpYbDBaWE4wTTBCd2NtOTBiMjV0WVdsc0xtTnZiU0lnUEd0
|
||||
aGVXdGxlWFJsYzNRegpRSEJ5YjNSdmJtMWhhV3d1WTI5dFBzTEFkUVFRQVFnQUtRVUNXM3J0dndZ
|
||||
TENRY0lBd0lKRU4xVkxlbDkKcVJRYUJCVUlDZ0lERmdJQkFoa0JBaHNEQWg0QkFBQ0dEZ2Y5SHVq
|
||||
aG9QUGN5SHpLd25JbFJJaENRL1dLCm13SVVFdEw4eU03aGRvci9zK0kyL1A3WkJHWE1ReXBKb3JD
|
||||
YTU1NUY2ODRMZnpWdUtBUVFMdXZpNHR6aQo5N2JSNE1ldHY4a2ptSUI1Rk0vNUhpWllWd090SDFK
|
||||
dU5iM2RQWG9CVjJha09ScnFCeVRjbjEyeUIwOVkKd0tZR0Y4K25XNFhLU1F2V3VBWWVIZ0dQKzMz
|
||||
ZTdCc0VvODhuRmJJUXl2cmUzUTN0TkJrWTVVVnA2L1M2ClpLZWJwaEFRQVlzM0ZVVlZVeThlZkhr
|
||||
aEFmZFlSdUFBUUFoWnJGanU0V1J0RGZkUHdLR0UzZDZsUGswSApNSFNTUXNHb2thQTVoTnUycE1S
|
||||
Mnl5UmtUa3JyNnRXbmlET2ZvSmtKcmc2VllHNVRwaHZnOE43dVdzZHQKZkhDdDBwWW9uYTRzclZx
|
||||
a0RzN0FUUVJiZXUyL0FRZ0F6b2tCSGZucnFXUXE4RUVSYUVlOUpmZkQ3V0FpCnZyU29lNDdxQ05l
|
||||
S2I2MmcvLzh0Q1dKMHVlRExTMFRyY0V4cnVzUi8rSFdoYUFTV2srL0lPTGhjRTcrVgp4V2Nab0dp
|
||||
bzNuc1puTktWdnFhendNSW1vMnFqdUllUnVCVkJqRW5OOERhOXlxNkJ3YVkvSEs2czM5Y3IKQVVV
|
||||
d2FtWjVuMDNtSFR6MzBMQllYR1VldVc5c3Z4NDIzbTlXb3N2WlQvUWRKWW1qMG44NmpGNGs2Tnh2
|
||||
ClV4ejR1bmV1YWt1Wld5NmNURHg1WFdWVWF1YzlyV1Z5Uzk3cjJ0NllpRlF6MTFiOU5oZm4rcDVs
|
||||
UmdZbgpzMzQwT1MyVmppK1BVeUVKZ2YzYi9MQlJ5V3Erbk1Vc2lRV09yYlQxblVCVzNRdDViWWhH
|
||||
MUhnT1o5eEoKVjd2dndSZHFwQ1p2cVFBUkFRQUJ3c0JmQkJnQkNBQVRCUUpiZXUyL0NSRGRWUzNw
|
||||
ZmFrVUdnSWJEQUFBClhrTUgvaTBoTnRwRWIrYUZONC9Ba0JCam1GOFJZV243anRyK2UyU05STHdF
|
||||
RUMxcmdmakhjWXZnanJFTQo2Y3hBcXVzSWJKSEdnSUVYZ0s1YUlNOHBGLzRuamN2VXVxa0x1b1o3
|
||||
QVJsanpwUTcvaHhyc0FNWnFYR2gKeEU4eXJZVlY0dGhhZWw0Q1NRUTRvRWlpbXB4Z28velE5bzhk
|
||||
NGNQUTM4Ni9VNEgvMm9OczFUMElCOTZWCkJsTy9pM0w5eGM4K2w4RG8vcm5ieVV1Ym9LUVNKZmtp
|
||||
RXNLMkRabEZoOVArdVltQ1AzVGJSb2NIUFZtVwpBT3NHVVhJSXROaVNTc05ORUlHeVBSNE8rMXRq
|
||||
VUJPMFNHRnZoVVZUNnJLYTlaYUVyMzI2ZmU2S0pmZU8KYTl4a21WZEdaQm9SdENmbHhiakdnYjRq
|
||||
dTJ3Z1E1TE5KWUNWZy9WRkxIRGI3MjQ9DQo9YmNvMw0KLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkg
|
||||
QkxPQ0stLS0tLQ0KDQo=
|
||||
-----------------------f0e64db835d0f5c3674df52a164b06bb--
|
||||
-----------------------4a9ea9f4dad3f36079bdb3f1e7b75bd0
|
||||
Content-Type: application/pgp-signature; name="signature.asc"
|
||||
Content-Description: OpenPGP digital signature
|
||||
Content-Disposition: attachment; filename="signature.asc"
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: ProtonMail
|
||||
Comment: https://protonmail.com
|
||||
|
||||
wsBcBAEBCAAQBQJbjodcCRDdVS3pfakUGgAAlhoH/2jBRjOSx5EdkiyyNcCT
|
||||
4DVm+ACoF1KTWE5fLRuDPvSiD934cFoZShJs32r0Wcj/4W4tVhLYzjjtf6xO
|
||||
Ymqe0p3o4oYxxMXIAd4COrnOPGjeD1ausqT6iUCAadqXoDYfowEg4f0Wd0RK
|
||||
ElsP/OZaDjsNoRE3WeRcHTr5XWZxhEsIMgnW591iaTliYvbysLoQ08i3G53c
|
||||
p6q+IANRznx5rDhMdo+shFvhcI2Zszg6X2WuCMhFtUyrqEN8WlZYXMX8PGPO
|
||||
1kNDRl7B7/r4Ap+FffLpeYw+8rG6lQXGc3RCOAnfMq9X/9Ziqzxr7flYtRJH
|
||||
RIzX2CG47PuGl/uvImFW/Iw=
|
||||
=t7ak
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
|
||||
-----------------------4a9ea9f4dad3f36079bdb3f1e7b75bd0--
|
||||
`
|
||||
body, atts, attHeaders, err := ParseMIME(testMessage)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("==BODY:")
|
||||
fmt.Println(body.GetBody())
|
||||
fmt.Println("==BODY HEADERS:")
|
||||
fmt.Println(body.GetHeaders())
|
||||
|
||||
fmt.Println("==ATTACHMENTS:")
|
||||
fmt.Println(len(atts))
|
||||
for i, attachment := range atts {
|
||||
fmt.Println("==ATTACHMENT HEADERS:")
|
||||
fmt.Println(attHeaders[i])
|
||||
fmt.Println("==ATTACHMENT:")
|
||||
fmt.Println(attachment)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue