11import crypto from 'node:crypto' ;
22import { domainToASCII } from 'node:url' ;
33import { ArgumentError } from '../errors.js' ;
4+ import { assertValidDate } from '../utils.js' ;
45
56// A fully-qualified domain name: two or more dot-separated labels of letters
67// (including non-ASCII), combining marks, digits, or hyphens, with no label
@@ -51,6 +52,19 @@ interface EmailProps {
5152 * true, the address will instead be sent as an MD5 hash.
5253 */
5354 hashAddress ?: boolean ;
55+ /**
56+ * The date and time of the most recent attempt to verify the email address,
57+ * if known. The time must not be before 1970-01-01T00:00:00Z or more than two
58+ * days in the future. The web service ignores a time outside this range and
59+ * returns a warning.
60+ */
61+ verificationTime ?: Date ;
62+ /**
63+ * Whether the most recent verification that the end user controls the email
64+ * address succeeded, for example by confirming a link sent to the address.
65+ * Omit this if no verification was attempted.
66+ */
67+ wasVerificationSuccessful ?: boolean ;
5468}
5569
5670/**
@@ -64,6 +78,19 @@ export default class Email implements EmailProps {
6478 public address ?: string ;
6579 /** @inheritDoc EmailProps.domain */
6680 public domain ?: string ;
81+ /**
82+ * The date and time of the most recent attempt to verify the email address,
83+ * if known. The time must not be before 1970-01-01T00:00:00Z or more than two
84+ * days in the future. The web service ignores a time outside this range and
85+ * returns a warning.
86+ */
87+ public verificationTime ?: Date ;
88+ /**
89+ * Whether the most recent verification that the end user controls the email
90+ * address succeeded, for example by confirming a link sent to the address.
91+ * Omit this if no verification was attempted.
92+ */
93+ public wasVerificationSuccessful ?: boolean ;
6794
6895 private static readonly typoDomains : { [ key : string ] : string } = {
6996 // gmail.com
@@ -327,6 +354,19 @@ export default class Email implements EmailProps {
327354 throw new ArgumentError ( '`email.domain` is an invalid domain' ) ;
328355 }
329356
357+ if ( email . verificationTime != null ) {
358+ assertValidDate ( email . verificationTime , 'email.verificationTime' ) ;
359+ }
360+
361+ if (
362+ email . wasVerificationSuccessful != null &&
363+ typeof email . wasVerificationSuccessful !== 'boolean'
364+ ) {
365+ throw new ArgumentError (
366+ '`email.wasVerificationSuccessful` must be a boolean'
367+ ) ;
368+ }
369+
330370 if ( email . address ) {
331371 if ( email . hashAddress ) {
332372 this . address = crypto . hash (
@@ -344,6 +384,14 @@ export default class Email implements EmailProps {
344384 if ( email . domain == null && email . address != null ) {
345385 this . domain = email . address . substring ( email . address . indexOf ( '@' ) + 1 ) ;
346386 }
387+
388+ // Copy the Date so that a later change to the caller's object does not
389+ // change the request.
390+ if ( email . verificationTime != null ) {
391+ this . verificationTime = new Date ( email . verificationTime . getTime ( ) ) ;
392+ }
393+
394+ this . wasVerificationSuccessful = email . wasVerificationSuccessful ;
347395 }
348396
349397 private cleanEmailAddress ( address : string ) {
0 commit comments