forked from Silverfish/proton-bridge
We build too many walls and not enough bridges
This commit is contained in:
94
internal/smtp/vcard_tools.go
Normal file
94
internal/smtp/vcard_tools.go
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2020 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ProtonMail/go-vcard"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||
)
|
||||
|
||||
type ContactMetadata struct {
|
||||
Email string
|
||||
Keys []string
|
||||
Scheme string
|
||||
Sign bool
|
||||
SignMissing bool
|
||||
Encrypt bool
|
||||
MIMEType string
|
||||
}
|
||||
|
||||
const (
|
||||
FieldPMScheme = "X-PM-SCHEME"
|
||||
FieldPMEncrypt = "X-PM-ENCRYPT"
|
||||
FieldPMSign = "X-PM-SIGN"
|
||||
FieldPMMIMEType = "X-PM-MIMETYPE"
|
||||
)
|
||||
|
||||
func GetContactMetadataFromVCards(cards []pmapi.Card, email string) (contactMeta *ContactMetadata, err error) {
|
||||
for _, card := range cards {
|
||||
dec := vcard.NewDecoder(strings.NewReader(card.Data))
|
||||
parsedCard, err := dec.Decode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
group := parsedCard.GetGroupByValue(vcard.FieldEmail, email)
|
||||
if len(group) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
keys := []string{}
|
||||
for _, key := range parsedCard.GetAllValueByGroup(vcard.FieldKey, group) {
|
||||
keybyte, err := base64.StdEncoding.DecodeString(strings.Split(key, "base64,")[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// It would be better to always have correct data on the server, but mistakes
|
||||
// can happen -- we had an issue where KEY was included in VCARD, but was empty.
|
||||
// It's valid and we need to handle it by not including it in the keys, which would fail later.
|
||||
if len(keybyte) > 0 {
|
||||
keys = append(keys, string(keybyte))
|
||||
}
|
||||
}
|
||||
scheme := parsedCard.GetValueByGroup(FieldPMScheme, group)
|
||||
// Warn: ParseBool treats 1, T, True, true as true and 0, F, Fale, false as false.
|
||||
// However PMEL declares 'true' is true, 'false' is false. every other string is true
|
||||
encrypt, _ := strconv.ParseBool(parsedCard.GetValueByGroup(FieldPMEncrypt, group))
|
||||
var sign, signMissing bool
|
||||
if len(parsedCard[FieldPMSign]) == 0 {
|
||||
signMissing = true
|
||||
} else {
|
||||
sign, _ = strconv.ParseBool(parsedCard.GetValueByGroup(FieldPMSign, group))
|
||||
signMissing = false
|
||||
}
|
||||
mimeType := parsedCard.GetValueByGroup(FieldPMMIMEType, group)
|
||||
return &ContactMetadata{
|
||||
Email: email,
|
||||
Keys: keys,
|
||||
Scheme: scheme,
|
||||
Sign: sign,
|
||||
SignMissing: signMissing,
|
||||
Encrypt: encrypt,
|
||||
MIMEType: mimeType,
|
||||
}, nil
|
||||
}
|
||||
return &ContactMetadata{}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user