Configurable email add domain (#287)

* Allow appending of local hostname to be configured via parsing context

Signed-off-by: Ben Magistro <koncept1@gmail.com>
Co-authored-by: Vincent Richard <vincent@vincent-richard.net>
This commit is contained in:
bmagistro 2023-12-31 10:03:30 -05:00 committed by GitHub
parent acfc0bbf82
commit 9b65b4de6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 12 deletions

View File

@ -176,7 +176,7 @@ emailAddress::emailAddress(const word& localName, const word& domainName)
void emailAddress::parseImpl(
const parsingContext& /* ctx */,
const parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -541,7 +541,7 @@ void emailAddress::parseImpl(
} else {
// If the domain part is missing, use local host name
if (domainPart.str().empty() && !atFound) {
if (ctx.getUseMyHostname() && domainPart.str().empty() && !atFound) {
domainPart << platform::getHandler()->getHostName();
}
@ -595,16 +595,28 @@ void emailAddress::generateImpl(
domainPart = domainNameToIDNA(m_domainName.getConvertedText(vmime::charsets::UTF_8));
}
os << localPart
<< "@"
<< domainPart;
if (newLinePos) {
if (!domainPart.empty()) {
os << localPart
<< "@"
<< domainPart;
*newLinePos = curLinePos
+ localPart.length()
+ 1 // @
+ domainPart.length();
if (newLinePos) {
*newLinePos = curLinePos
+ localPart.length()
+ 1 // @
+ domainPart.length();
}
} else {
// this should only be true if m_useMyHostname is false and an address without
// an `@` is encountered
os << localPart;
if (newLinePos) {
*newLinePos = curLinePos
+ localPart.length();
}
}
}
@ -698,8 +710,12 @@ const text emailAddress::toText() const {
text txt;
txt.appendWord(make_shared <vmime::word>(m_localName));
txt.appendWord(make_shared <vmime::word>("@", vmime::charsets::US_ASCII));
txt.appendWord(make_shared <vmime::word>(m_domainName));
if (!m_domainName.empty()) {
// this should only be skipped if m_useMyHostname is false and an address without
// an `@` is encountered
txt.appendWord(make_shared <vmime::word>("@", vmime::charsets::US_ASCII));
txt.appendWord(make_shared <vmime::word>(m_domainName));
}
return txt;
}

View File

@ -61,4 +61,16 @@ void parsingContext::setHeaderParseErrorRecoveryMethod(
}
bool parsingContext::getUseMyHostname() const {
return m_useMyHostname;
}
void parsingContext::setUseMyHostname(bool useMyHostname) {
m_useMyHostname = useMyHostname;
}
} // vmime

View File

@ -77,9 +77,28 @@ public:
*/
headerParseRecoveryMethod::headerLineError getHeaderParseErrorRecoveryMethod() const;
/** Return the current hostname adding behavior when parsing/creating a header field that
* utilizes a domain name.
*
* @retval true The local hostname will be appended if a domain is not present
* @retval false The local hostname will not be appended even if a domain is not present
*/
bool getUseMyHostname() const;
/** Enables/disables appending the local hostname in header fields if a domain is not
* not provided and it is required. The default is to append. Changing this can result
* in fields that would violate various RFCs.
*/
void setUseMyHostname(bool useMyHostname);
protected:
headerParseRecoveryMethod::headerLineError m_headerParseErrorRecovery;
/** Flag to indicate if the local hostname should be used/appended
* for header fields when one is not present.
*/
bool m_useMyHostname{true};
};

View File

@ -192,6 +192,16 @@ void path::generateImpl(
*newLinePos = curLinePos + 2;
}
} else if (!m_localPart.empty() && m_domain.empty()) {
// this should only be true if m_useMyHostname is false and an address without
// an `@` is encountered
os << "<" << m_localPart << ">";
if (newLinePos) {
*newLinePos = curLinePos + m_localPart.length() + 2;
}
} else {
os << "<" << m_localPart << "@" << m_domain << ">";