Skip to main content

async_graphql_extras/validators/
email_address.rs

1use async_graphql::{InputValueError, Scalar, ScalarType, Value};
2
3/// Email addresss newtype
4///
5/// Can be used as a scalar to parse a string into a newtype
6///
7/// ```ignore
8/// async fn handler(&self, EmailAddress(email): EmailAddress) {
9/// }
10/// ```
11#[cfg_attr(docsrs, doc(cfg(feature = "email-address")))]
12pub struct EmailAddress(pub email_address::EmailAddress);
13
14#[Scalar(
15    name = "EmailAddress",
16    specified_by_url = "https://en.wikipedia.org/wiki/Email_address#Syntax"
17)]
18impl ScalarType for EmailAddress {
19    fn parse(value: Value) -> Result<Self, InputValueError<Self>> {
20        if let Value::String(string) = &value {
21            Ok(Self(string.parse()?))
22        } else {
23            Err(InputValueError::expected_type(value))
24        }
25    }
26
27    fn to_value(&self) -> Value {
28        Value::String(self.0.to_string())
29    }
30}
31
32#[cfg(test)]
33mod test {
34    use super::*;
35
36    fn email(email: &str) -> Result<EmailAddress, InputValueError<EmailAddress>> {
37        EmailAddress::parse(Value::String(email.into()))
38    }
39
40    #[test]
41    fn test_email() {
42        assert!(email("joe@example.com").is_ok());
43        assert!(email("joe.test@example.com").is_ok());
44        assert!(email("email@example-one.com").is_ok());
45        assert!(email("1234567890@example.com").is_ok());
46
47        assert!(email("plainaddress").is_err());
48        assert!(email("@example.com").is_err());
49        assert!(email("email.example.com").is_err());
50    }
51}