1/*2Maddy Mail Server - Composable all-in-one email server.3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors45This program is free software: you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation, either version 3 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program. If not, see <https://www.gnu.org/licenses/>.17*/1819package smtp2021import (22 "fmt"23 "regexp"24 "time"25)2627// Taken from https://github.com/emersion/go-imap/blob/09c1d69/date.go.2829var dateTimeLayouts = [...]string{30 // Defined in RFC 5322 section 3.3, mentioned as env-date in RFC 3501 page 84.31 "Mon, 02 Jan 2006 15:04:05 -0700",32 "_2 Jan 2006 15:04:05 -0700",33 "_2 Jan 2006 15:04:05 MST",34 "_2 Jan 2006 15:04 -0700",35 "_2 Jan 2006 15:04 MST",36 "_2 Jan 06 15:04:05 -0700",37 "_2 Jan 06 15:04:05 MST",38 "_2 Jan 06 15:04 -0700",39 "_2 Jan 06 15:04 MST",40 "Mon, _2 Jan 2006 15:04:05 -0700",41 "Mon, _2 Jan 2006 15:04:05 MST",42 "Mon, _2 Jan 2006 15:04 -0700",43 "Mon, _2 Jan 2006 15:04 MST",44 "Mon, _2 Jan 06 15:04:05 -0700",45 "Mon, _2 Jan 06 15:04:05 MST",46 "Mon, _2 Jan 06 15:04 -0700",47 "Mon, _2 Jan 06 15:04 MST",48}4950// TODO: this is a blunt way to strip any trailing CFWS (comment). A sharper51// one would strip multiple CFWS, and only if really valid according to52// RFC5322.53var commentRE = regexp.MustCompile(`[ \t]+\(.*\)$`)5455// Try parsing the date based on the layouts defined in RFC 5322, section 3.3.56// Inspired by https://github.com/golang/go/blob/master/src/net/mail/message.go57func parseMessageDateTime(maybeDate string) (time.Time, error) {58 maybeDate = commentRE.ReplaceAllString(maybeDate, "")59 for _, layout := range dateTimeLayouts {60 parsed, err := time.Parse(layout, maybeDate)61 if err == nil {62 return parsed, nil63 }64 }65 return time.Time{}, fmt.Errorf("date %s could not be parsed", maybeDate)66}