Change names of EmailAddressParserConfig properties

This commit is contained in:
cketti 2023-06-15 16:52:50 +02:00
parent e4574e08d9
commit 20d1e56639
3 changed files with 51 additions and 46 deletions

View file

@ -56,11 +56,13 @@ internal class EmailAddressParser(
parserError(TotalLengthExceeded)
}
if (!config.allowLocalPartRequiringQuotedString && Warning.QuotedStringInLocalPart in emailAddress.warnings) {
if (
!config.isLocalPartRequiringQuotedStringAllowed && Warning.QuotedStringInLocalPart in emailAddress.warnings
) {
parserError(LocalPartRequiresQuotedString, position = 0)
}
if (!config.allowEmptyLocalPart && Warning.EmptyLocalPart in emailAddress.warnings) {
if (!config.isEmptyLocalPartAllowed && Warning.EmptyLocalPart in emailAddress.warnings) {
parserError(EmptyLocalPart, position = 1)
}
@ -83,7 +85,7 @@ internal class EmailAddressParser(
readDotString()
}
character == DQUOTE -> {
if (config.allowQuotedLocalPart) {
if (config.isQuotedLocalPartAllowed) {
readQuotedString()
} else {
parserError(QuotedStringInLocalPart)

View file

@ -3,39 +3,36 @@ package app.k9mail.core.common.mail
/**
* Configuration to control the behavior when parsing an email address into [EmailAddress].
*
* @param allowQuotedLocalPart When this is `true`, the parsing step allows email addresses with a local part encoded
* as quoted string, e.g. `"foo bar"@domain.example`. Otherwise, the parser will throw an [EmailAddressParserException]
* as soon as a quoted string is encountered.
* @param isQuotedLocalPartAllowed When this is `true`, the parsing step allows email addresses with a local part
* encoded as quoted string, e.g. `"foo bar"@domain.example`. Otherwise, the parser will throw an
* [EmailAddressParserException] as soon as a quoted string is encountered.
* Quoted strings in local parts are not widely used. It's recommended to disallow them whenever possible.
*
* @param allowLocalPartRequiringQuotedString Email addresses whose local part requires the use of a quoted string are
* only allowed when this is `true`. This is separate from [allowQuotedLocalPart] because one might want to allow email
* addresses that unnecessarily use a quoted string, e.g. `"test"@domain.example` ([allowQuotedLocalPart] = `true`,
* [allowLocalPartRequiringQuotedString] = `false`; [EmailAddress] will not retain the original form and treat this
* address exactly like `test@domain.example`). When allowing this, remember to use the value of [EmailAddress.address]
* instead of retaining the original user input.
* @param isLocalPartRequiringQuotedStringAllowed Email addresses whose local part requires the use of a quoted string
* are only allowed when this is `true`. This is separate from [isQuotedLocalPartAllowed] because one might want to
* allow email addresses that unnecessarily use a quoted string, e.g. `"test"@domain.example`
* ([isQuotedLocalPartAllowed] = `true`, [isLocalPartRequiringQuotedStringAllowed] = `false`; [EmailAddress] will not
* retain the original form and treat this address exactly like `test@domain.example`). When allowing this, remember to
* use the value of [EmailAddress.address] instead of retaining the original user input.
*
* The value of this property is ignored if [allowQuotedLocalPart] is `false`.
* The value of this property is ignored if [isQuotedLocalPartAllowed] is `false`.
*
* @param allowEmptyLocalPart Email addresses with an empty local part (e.g. `""@domain.example`) are only allowed if
* this value is `true`.
* @param isEmptyLocalPartAllowed Email addresses with an empty local part (e.g. `""@domain.example`) are only allowed
* if this value is `true`.
*
* The value of this property is ignored if at least one of [allowQuotedLocalPart] and
* [allowLocalPartRequiringQuotedString] is `false`.
* The value of this property is ignored if at least one of [isQuotedLocalPartAllowed] and
* [isLocalPartRequiringQuotedStringAllowed] is `false`.
*/
data class EmailAddressParserConfig(
val allowQuotedLocalPart: Boolean,
val allowLocalPartRequiringQuotedString: Boolean,
val allowEmptyLocalPart: Boolean = false,
val isQuotedLocalPartAllowed: Boolean,
val isLocalPartRequiringQuotedStringAllowed: Boolean,
val isEmptyLocalPartAllowed: Boolean = false,
) {
companion object {
/**
* This configuration should match what `EmailAddressValidator` currently allows.
*/
val DEFAULT = EmailAddressParserConfig(
allowQuotedLocalPart = true,
allowLocalPartRequiringQuotedString = true,
allowEmptyLocalPart = false,
isQuotedLocalPartAllowed = true,
isLocalPartRequiringQuotedStringAllowed = true,
isEmptyLocalPartAllowed = false,
)
}
}

View file

@ -40,7 +40,10 @@ class EmailAddressParserTest {
@Test
fun `quoted local part`() {
val emailAddress = parseEmailAddress("\"one two\"@domain.example", allowLocalPartRequiringQuotedString = true)
val emailAddress = parseEmailAddress(
address = "\"one two\"@domain.example",
isLocalPartRequiringQuotedStringAllowed = true,
)
assertThat(emailAddress.localPart).isEqualTo("one two")
assertThat(emailAddress.domain).isEqualTo(EmailDomain("domain.example"))
@ -51,8 +54,8 @@ class EmailAddressParserTest {
assertFailure {
parseEmailAddress(
address = "\"one two\"@domain.example",
allowQuotedLocalPart = true,
allowLocalPartRequiringQuotedString = false,
isQuotedLocalPartAllowed = true,
isLocalPartRequiringQuotedStringAllowed = false,
)
}.isInstanceOf<EmailAddressParserException>().all {
prop(EmailAddressParserException::error).isEqualTo(LocalPartRequiresQuotedString)
@ -65,8 +68,8 @@ class EmailAddressParserTest {
fun `unnecessarily quoted local part`() {
val emailAddress = parseEmailAddress(
address = "\"user\"@domain.example",
allowQuotedLocalPart = true,
allowLocalPartRequiringQuotedString = false,
isQuotedLocalPartAllowed = true,
isLocalPartRequiringQuotedStringAllowed = false,
)
assertThat(emailAddress.localPart).isEqualTo("user")
@ -77,7 +80,7 @@ class EmailAddressParserTest {
@Test
fun `unnecessarily quoted local part not allowed`() {
assertFailure {
parseEmailAddress("\"user\"@domain.example", allowQuotedLocalPart = false)
parseEmailAddress("\"user\"@domain.example", isQuotedLocalPartAllowed = false)
}.isInstanceOf<EmailAddressParserException>().all {
prop(EmailAddressParserException::error).isEqualTo(QuotedStringInLocalPart)
prop(EmailAddressParserException::position).isEqualTo(0)
@ -87,7 +90,10 @@ class EmailAddressParserTest {
@Test
fun `quoted local part containing double quote character`() {
val emailAddress = parseEmailAddress(""""a\"b"@domain.example""", allowLocalPartRequiringQuotedString = true)
val emailAddress = parseEmailAddress(
address = """"a\"b"@domain.example""",
isLocalPartRequiringQuotedStringAllowed = true,
)
assertThat(emailAddress.localPart).isEqualTo("a\"b")
assertThat(emailAddress.domain).isEqualTo(EmailDomain("domain.example"))
@ -96,7 +102,7 @@ class EmailAddressParserTest {
@Test
fun `empty local part`() {
val emailAddress = parseEmailAddress("\"\"@domain.example", allowEmptyLocalPart = true)
val emailAddress = parseEmailAddress("\"\"@domain.example", isEmptyLocalPartAllowed = true)
assertThat(emailAddress.localPart).isEqualTo("")
assertThat(emailAddress.domain).isEqualTo(EmailDomain("domain.example"))
@ -108,8 +114,8 @@ class EmailAddressParserTest {
assertFailure {
parseEmailAddress(
address = "\"\"@domain.example",
allowLocalPartRequiringQuotedString = true,
allowEmptyLocalPart = false,
isLocalPartRequiringQuotedStringAllowed = true,
isEmptyLocalPartAllowed = false,
)
}.isInstanceOf<EmailAddressParserException>().all {
prop(EmailAddressParserException::error).isEqualTo(EmptyLocalPart)
@ -154,7 +160,7 @@ class EmailAddressParserTest {
@Test
fun `obsolete syntax`() {
assertFailure {
parseEmailAddress("\"quoted\".atom@domain.example", allowLocalPartRequiringQuotedString = true)
parseEmailAddress("\"quoted\".atom@domain.example", isLocalPartRequiringQuotedStringAllowed = true)
}.isInstanceOf<EmailAddressParserException>().all {
prop(EmailAddressParserException::error).isEqualTo(UnexpectedCharacter)
prop(EmailAddressParserException::position).isEqualTo(8)
@ -187,7 +193,7 @@ class EmailAddressParserTest {
@Test
fun `quoted local part missing closing double quote`() {
assertFailure {
parseEmailAddress("\"invalid@domain.example", allowLocalPartRequiringQuotedString = true)
parseEmailAddress("\"invalid@domain.example", isLocalPartRequiringQuotedStringAllowed = true)
}.isInstanceOf<EmailAddressParserException>().all {
prop(EmailAddressParserException::error).isEqualTo(UnexpectedCharacter)
prop(EmailAddressParserException::position).isEqualTo(23)
@ -198,7 +204,7 @@ class EmailAddressParserTest {
@Test
fun `quoted text containing unsupported character`() {
assertFailure {
parseEmailAddress("\"ä\"@domain.example", allowLocalPartRequiringQuotedString = true)
parseEmailAddress("\"ä\"@domain.example", isLocalPartRequiringQuotedStringAllowed = true)
}.isInstanceOf<EmailAddressParserException>().all {
prop(EmailAddressParserException::error).isEqualTo(InvalidQuotedString)
prop(EmailAddressParserException::position).isEqualTo(1)
@ -209,7 +215,7 @@ class EmailAddressParserTest {
@Test
fun `quoted text containing unsupported escaped character`() {
assertFailure {
parseEmailAddress(""""\ä"@domain.example""", allowLocalPartRequiringQuotedString = true)
parseEmailAddress(""""\ä"@domain.example""", isLocalPartRequiringQuotedStringAllowed = true)
}.isInstanceOf<EmailAddressParserException>().all {
prop(EmailAddressParserException::error).isEqualTo(InvalidQuotedString)
prop(EmailAddressParserException::position).isEqualTo(3)
@ -257,14 +263,14 @@ class EmailAddressParserTest {
private fun parseEmailAddress(
address: String,
allowEmptyLocalPart: Boolean = false,
allowLocalPartRequiringQuotedString: Boolean = allowEmptyLocalPart,
allowQuotedLocalPart: Boolean = allowLocalPartRequiringQuotedString,
isEmptyLocalPartAllowed: Boolean = false,
isLocalPartRequiringQuotedStringAllowed: Boolean = isEmptyLocalPartAllowed,
isQuotedLocalPartAllowed: Boolean = isLocalPartRequiringQuotedStringAllowed,
): EmailAddress {
val config = EmailAddressParserConfig(
allowQuotedLocalPart,
allowLocalPartRequiringQuotedString,
allowEmptyLocalPart,
isQuotedLocalPartAllowed,
isLocalPartRequiringQuotedStringAllowed,
isEmptyLocalPartAllowed,
)
return EmailAddressParser(address, config).parse()
}