diff --git a/parsemail.go b/parsemail.go index 6a60192..62e1042 100644 --- a/parsemail.go +++ b/parsemail.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "mime" "mime/multipart" + "mime/quotedprintable" "net/mail" "strings" "time" @@ -45,9 +46,11 @@ func Parse(r io.Reader) (email Email, err error) { case contentTypeMultipartRelated: email.TextBody, email.HTMLBody, email.EmbeddedFiles, err = parseMultipartRelated(msg.Body, params["boundary"]) case contentTypeTextPlain: + msg.Body, _ = decodeContent(msg.Body, msg.Header.Get("Content-Transfer-Encoding")) message, _ := ioutil.ReadAll(msg.Body) email.TextBody = strings.TrimSuffix(string(message[:]), "\n") case contentTypeTextHtml: + msg.Body, _ = decodeContent(msg.Body, msg.Header.Get("Content-Transfer-Encoding")) message, _ := ioutil.ReadAll(msg.Body) email.HTMLBody = strings.TrimSuffix(string(message[:]), "\n") default: @@ -361,6 +364,8 @@ func decodeContent(content io.Reader, encoding string) (io.Reader, error) { } return bytes.NewReader(dd), nil + case "quoted-printable": + return quotedprintable.NewReader(content), nil case "": return content, nil default: @@ -483,11 +488,11 @@ type Email struct { ResentMessageID string ContentType string - Content io.Reader + Content io.Reader HTMLBody string TextBody string Attachments []Attachment EmbeddedFiles []EmbeddedFile -} \ No newline at end of file +} diff --git a/parsemail_test.go b/parsemail_test.go index 109e734..d714cc9 100644 --- a/parsemail_test.go +++ b/parsemail_test.go @@ -274,7 +274,7 @@ So, "Hello".`, messageID: "1234@local.machine.example", date: parseDate("Fri, 21 Nov 1997 09:55:06 -0600"), contentType: `image/jpeg; x-unix-mode=0644; name="image.gif"`, - content: `GIF89a;`, + content: `GIF89a;`, }, 9: { contentType: `multipart/mixed; boundary="0000000000007e2bb40587e36196"`, @@ -372,15 +372,15 @@ So, "Hello".`, htmlBody: "

", attachments: []attachmentData{ { - filename: "unencoded.csv", - contentType: "application/csv", - data: fmt.Sprintf("\n"+`"%s", "%s", "%s", "%s", "%s"`+"\n"+`"%s", "%s", "%s", "%s", "%s"`+"\n", "Some", "Data", "In", "Csv", "Format", "Foo", "Bar", "Baz", "Bum", "Poo"), + filename: "unencoded.csv", + contentType: "application/csv", + data: fmt.Sprintf("\n"+`"%s", "%s", "%s", "%s", "%s"`+"\n"+`"%s", "%s", "%s", "%s", "%s"`+"\n", "Some", "Data", "In", "Csv", "Format", "Foo", "Bar", "Baz", "Bum", "Poo"), }, }, }, 13: { contentType: "multipart/related; boundary=\"000000000000ab2e2205a26de587\"", - mailData: multipartRelatedExample, + mailData: multipartRelatedExample, subject: "Saying Hello", from: []mail.Address{ { @@ -389,7 +389,7 @@ So, "Hello".`, }, }, sender: mail.Address{ - Name: "Michael Jones", + Name: "Michael Jones", Address: "mjones@machine.example", }, to: []mail.Address{ @@ -401,7 +401,79 @@ So, "Hello".`, messageID: "1234@local.machine.example", date: parseDate("Fri, 21 Nov 1997 09:55:06 -0600"), htmlBody: "
Time for the egg.



", - textBody: "Time for the egg.", + textBody: "Time for the egg.", + }, + 14: { + contentType: "text/plain; charset=utf-8", + mailData: rfc2045exampleA, + subject: "Lead from Allstate LeadVantage", + from: []mail.Address{ + { + Address: "LVsupport@allstateleadvantage.com", + }, + }, + to: []mail.Address{ + { + Address: "test@email.com", + }, + }, + replyTo: []mail.Address{ + { + Address: "no-reply@allstateleadvantage.com", + }, + }, + messageID: "0100017fcf817777-481efc68-4a9a-4c11-ba2c-40ff0357e7b1-000000@email.amazonses.com", + date: parseDate("Mon, 28 Mar 2022 07:50:42 +0000"), + textBody: rfc2045exampleAtext, + }, + 15: { + contentType: `text/html; charset="utf-8"`, + mailData: rfc2045exampleB, + subject: "New Business Property/Casualty Lead Received (#245200111)", + from: []mail.Address{ + { + Name: "AllWebLeads", + Address: "no-reply@allwebleads.com", + }, + }, + to: []mail.Address{ + { + Address: "sample@example.com", + }, + }, + replyTo: []mail.Address{ + { + Address: "no-reply@allwebleads.com", + }, + }, + messageID: "1187856165.40703531648591546580.JavaMail.app@rapp51.atlis1", + date: parseDate("Tue, 29 Mar 2022 22:05:46 +0000"), + htmlBody: rfc2045exampleBhtml, + }, + 16: { + contentType: "multipart/related; boundary=\"000000000000ab2e2205a26de587\"", + mailData: multipartRelatedExampleQuoted, + subject: "Saying Hello", + from: []mail.Address{ + { + Name: "John Doe", + Address: "jdoe@machine.example", + }, + }, + sender: mail.Address{ + Name: "Michael Jones", + Address: "mjones@machine.example", + }, + to: []mail.Address{ + { + Name: "Mary Smith", + Address: "mary@example.net", + }, + }, + messageID: "1234@local.machine.example", + date: parseDate("Fri, 21 Nov 1997 09:55:06 -0600"), + htmlBody: rfc2045exampleBhtml, + textBody: "Time for the egg. Should we hardboil the egg or fry it. We can scramble it or poach it.", }, } @@ -595,9 +667,9 @@ func parseDate(in string) time.Time { } type attachmentData struct { - filename string - contentType string - data string + filename string + contentType string + data string } type embeddedFileData struct { @@ -946,3 +1018,227 @@ Content-Disposition: attachment; --f403045f1dcc043a44054c8e6bbf-- ` +var rfc2045exampleA = `From 0100017fcf817777-481efc68-4a9a-4c11-ba2c-40ff0357e7b1-000000@amazonses.com Mon Mar 28 07:50:43 2022 +Return-Path: <0100017fcf817777-481efc68-4a9a-4c11-ba2c-40ff0357e7b1-000000@amazonses.com> +X-Original-To: test@email.com +Delivered-To: leads@reciever.com +Message-ID: <0100017fcf817777-481efc68-4a9a-4c11-ba2c-40ff0357e7b1-000000@email.amazonses.com> +Date: Mon, 28 Mar 2022 07:50:42 +0000 +Subject: Lead from Allstate LeadVantage +From: LVsupport@allstateleadvantage.com +Reply-To: no-reply@allstateleadvantage.com +To: test@email.com +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + + +You just received a lead! Please check your lead management system, or u= +se the contact information +below. Please do not respond to this email ad= +dress, as it is not active. You may also view your leads +in Allstate Lead= +Vantage. Please call Allstate LeadVantage Support at 855-317-4233 or sign u= +p here: +https://allstateleadvantage.com/#/orders/list + +Lead Informati= +on: +Unique ID: 138296007 +Vertical: Auto Insurance +Alliance URL: https= +://agencygateway.allstate.com/ALLIANCE/launch?AgentNumber=3DA0c3858&ST=3DNV= +&FunctionType=3DAF&SourceOfLaunchPoint=3D01&ControlNumber=3D198220870336180= + +Contact Information: +First Name: Brenda +Last Name: Qualls +Phone Nu= +mber: (702) 485-1038 +Email Address: brendaqualls29@yahoo.com +Street Add= +ress: 3236 Brayton Mist Dr +City: North Las Vegas +State: NV +Zip: 89081= + +Are You A Homeowner: Yes +Best Time To Contact:=20 +Vendor: +Vendor Nam= +e: Inside Response +Order Information: +Name: Custom Order 1 +Policy Det= +ails: +Self Credit Rating: Good (620 - 719) +Currently Insured: Yes +Cur= +rent Insurance Company: State Farm County +Insured Since: 03/28/2020 +Pol= +icy Start: 03/28/2020 +Policy Expiration: 05/28/2022 +Desired Coverage Ty= +pe: standard +Desired Collision Deductible: 1000 +Desired Comprehensive D= +eductible: 1000 +Driver 1: +Gender: female +Marital Status: married +Ed= +ucation Level: ged +Occupation: other +Date of Birth: 01/29/1981 +Age Li= +censed: 19 +Has Valid License: Yes +Has DUI: No +Requires SR-22: No +Re= +lation to applicant: self +Years Employed: 2 +Years at Residence: 2 +Has= + Tickets / Accidents: No +Vehicle 1: +Type: 2006 LEXUS SC 430 2WD CONVERT= +IBLE - 4.3L V8 FI DOHC 32V F +Vin: JTHFN48Y060000000 +Leased: No +Pri= +mary Use: Pleasure Use Only +Commute Days: 5 +Daily Mileage: 5 +Annual M= +ileage: 15000 +Has Alarm: Yes +Garage: nocover +` + +var rfc2045exampleAtext string = ` +You just received a lead! Please check your lead management system, or use the contact information +below. Please do not respond to this email address, as it is not active. You may also view your leads +in Allstate LeadVantage. Please call Allstate LeadVantage Support at 855-317-4233 or sign up here: +https://allstateleadvantage.com/#/orders/list + +Lead Information: +Unique ID: 138296007 +Vertical: Auto Insurance +Alliance URL: https://agencygateway.allstate.com/ALLIANCE/launch?AgentNumber=A0c3858&ST=NV&FunctionType=AF&SourceOfLaunchPoint=01&ControlNumber=198220870336180 +Contact Information: +First Name: Brenda +Last Name: Qualls +Phone Number: (702) 485-1038 +Email Address: brendaqualls29@yahoo.com +Street Address: 3236 Brayton Mist Dr +City: North Las Vegas +State: NV +Zip: 89081 +Are You A Homeowner: Yes +Best Time To Contact: +Vendor: +Vendor Name: Inside Response +Order Information: +Name: Custom Order 1 +Policy Details: +Self Credit Rating: Good (620 - 719) +Currently Insured: Yes +Current Insurance Company: State Farm County +Insured Since: 03/28/2020 +Policy Start: 03/28/2020 +Policy Expiration: 05/28/2022 +Desired Coverage Type: standard +Desired Collision Deductible: 1000 +Desired Comprehensive Deductible: 1000 +Driver 1: +Gender: female +Marital Status: married +Education Level: ged +Occupation: other +Date of Birth: 01/29/1981 +Age Licensed: 19 +Has Valid License: Yes +Has DUI: No +Requires SR-22: No +Relation to applicant: self +Years Employed: 2 +Years at Residence: 2 +Has Tickets / Accidents: No +Vehicle 1: +Type: 2006 LEXUS SC 430 2WD CONVERTIBLE - 4.3L V8 FI DOHC 32V F +Vin: JTHFN48Y060000000 +Leased: No +Primary Use: Pleasure Use Only +Commute Days: 5 +Daily Mileage: 5 +Annual Mileage: 15000 +Has Alarm: Yes +Garage: nocover` + +var rfc2045exampleB string = `From v-biheobc_begnlldjf_icanamoe_icanamoe_a-1@bounce.allweb.mkt3103.com Tue Mar 29 22:05:46 2022 +Return-Path: +X-Original-To: sample@example.com +Delivered-To: leads@reciever.com +Received: by mail2792.allweb.mkt3188.com id h8e1bk2r7ao5 for ; Tue, 29 Mar 2022 22:05:46 +0000 (envelope-from ) +Date: Tue, 29 Mar 2022 22:05:46 +0000 (GMT) +From: AllWebLeads +Reply-To: no-reply@allwebleads.com +To: sample@example.com +Message-ID: <1187856165.40703531648591546580.JavaMail.app@rapp51.atlis1> +Subject: New Business Property/Casualty Lead Received (#245200111) +Content-Type: text/html; charset="utf-8" +Content-Transfer-Encoding: quoted-printable + +
+=09
Time for the egg.
+=09

+=09


+=09
Should we hardboil the egg or fry it. We can scramble it or poach i= +t.
+
` + +var rfc2045exampleBhtml string = `
+
Time for the egg.
+

+


+
Should we hardboil the egg or fry it. We can scramble it or poach it.
+
` +var multipartRelatedExampleQuoted = `MIME-Version: 1.0 +From: John Doe +Sender: Michael Jones +To: Mary Smith +Subject: Saying Hello +Date: Fri, 21 Nov 1997 09:55:06 -0600 +Message-ID: <1234@local.machine.example> +Subject: ooops +To: test@example.rocks +Content-Type: multipart/related; boundary="000000000000ab2e2205a26de587" + +--000000000000ab2e2205a26de587 +Content-Type: multipart/alternative; boundary="000000000000ab2e1f05a26de586" + +--000000000000ab2e1f05a26de586 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + +Time for the egg. Should we hardboil the egg or fry it. We can scramble it = +or poach it. + +--000000000000ab2e1f05a26de586 +Content-Type: text/html; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + +
+=09
Time for the egg.
+=09

+=09


+=09
Should we hardboil the egg or fry it. We can scramble it or poach i= +t.
+
+ +--000000000000ab2e1f05a26de586-- + + +--000000000000ab2e2205a26de587-- +`