package format import ( "errors" "fmt" gomail "net/mail" "strings" "unicode" "git.sr.ht/~sircmpwn/aerc/models" ) func parseAddress(address string) *gomail.Address { addrs, err := gomail.ParseAddress(address) if err != nil { return nil } return addrs } func ParseMessageFormat( fromAddress string, format string, timestampformat string, accountName string, number int, msg *models.MessageInfo, marked bool) (string, []interface{}, error) { retval := make([]byte, 0, len(format)) var args []interface{} accountFromAddress := parseAddress(fromAddress) var c rune for i, ni := 0, 0; i < len(format); { ni = strings.IndexByte(format[i:], '%') if ni < 0 { ni = len(format) retval = append(retval, []byte(format[i:ni])...) break } ni += i + 1 // Check for fmt flags if ni == len(format) { goto handle_end_error } c = rune(format[ni]) if c == '+' || c == '-' || c == '#' || c == ' ' || c == '0' { ni++ } // Check for precision and width if ni == len(format) { goto handle_end_error } c = rune(format[ni]) for unicode.IsDigit(c) { ni++ c = rune(format[ni]) } if c == '.' { ni++ c = rune(format[ni]) for unicode.IsDigit(c) { ni++ c = rune(format[ni]) } } retval = append(retval, []byte(format[i:ni])...) // Get final format verb if ni == len(format) { goto handle_end_error } c = rune(format[ni]) switch c { case '%': retval = append(retval, '%') case 'a': if len(msg.Envelope.From) == 0 { return "", nil, errors.New("found no address for sender") } addr := msg.Envelope.From[0] retval = append(retval, 's') args = append(args, fmt.Sprintf("%s@%s", addr.Mailbox, addr.Host)) case 'A': var addr *models.Address if len(msg.Envelope.ReplyTo) == 0 { if len(msg.Envelope.From) == 0 { return "", nil, errors.New("found no address for sender or reply-to") } else { addr = msg.Envelope.From[0] } } else { addr = msg.Envelope.ReplyTo[0] } retval = append(retval, 's') args = append(args, fmt.Sprintf("%s@%s", addr.Mailbox, addr.Host)) case 'C': retval = append(retval, 'd') args = append(args, number) case 'd': retval = append(retval, 's') args = append(args, msg.InternalDate.Format(timestampformat)) case 'D': retval = append(retval, 's') args = append(args, msg.InternalDate.Local().Format(timestampformat)) case 'f': if len(msg.Envelope.From) == 0 { return "", nil, errors.New("found no address for sender") } addr := msg.Envelope.From[0].Format() retval = append(retval, 's') args = append(args, addr) case 'F': if len(msg.Envelope.From) == 0 { return "", nil, errors.New("found no address for sender") } addr := msg.Envelope.From[0] var val string if addr.Name == accountFromAddress.Name && len(msg.Envelope.To) != 0 { addr = msg.Envelope.To[0] } if addr.Name != "" { val = addr.Name } else { val = fmt.Sprintf("%s@%s", addr.Mailbox, addr.Host) } retval = append(retval, 's') args = append(args, val) case 'g': retval = append(retval, 's') args = append(args, strings.Join(msg.Labels, ", ")) case 'i': retval = append(retval, 's') args = append(args, msg.Envelope.MessageId) case 'n': if len(msg.Envelope.From) == 0 { return "", nil, errors.New("found no address for sender") } addr := msg.Envelope.From[0] var val string if addr.Name != "" { val = addr.Name } else { val = fmt.Sprintf("%s@%s", addr.Mailbox, addr.Host) } retval = append(retval, 's') args = append(args, val) case 'r': addrs := models.FormatAddresses(msg.Envelope.To) retval = append(retval, 's') args = append(args, addrs) case 'R': addrs := models.FormatAddresses(msg.Envelope.Cc) retval = append(retval, 's') args = append(args, addrs) case 's': retval = append(retval, 's') args = append(args, msg.Envelope.Subject) case 't': if len(msg.Envelope.To) == 0 { return "", nil, errors.New("found no address for recipient") } addr := msg.Envelope.To[0] retval = append(retval, 's') args = append(ar