Skip to content
Mason Hicks edited this page Sep 3, 2024 · 4 revisions

Requirements

User Story

Functional:

  1. As a service provider, I want to be able to verify user email addresses so that I can prevent spam or other abuse.
  2. As a service provider, I want to be able to verify user email addresses so that I can provide a ticketing system or other outlet.
  3. As a service provider, I want to be able to provide a "hop" for ticketing outlets/similar so that the workflow is the same every time.
  4. As a service user, I want to be able to see confirmation that my hopped email or ticket was delivered so that I know it is not going to the void.
  5. As a service user, I want to be able to easily perform my email verification instead of having ambiguous prompts that are hard to read.

Non-functional:

  1. As a service provider, I want there to be an interface specifically for creating challenges and sending them as emails so that I can support any variety of these requests.
  2. As a service provider, I want to create an individual server connection to handle each request in order to prevent workers from having to compete for a use of the connection.
  3. As a service provider, I want to provide TLS for my mailserver to prevent abuse.
  4. As a service provider, I want to be able to configure CORS addresses to prevent misuse by attackers.
  5. As a service provider, I want to routinely remove outdated challenges in order to prevent clutter.
  6. As a service provider, I want to be able to configure timeout on the application's email features as this may differ between use cases.
  7. As a service provider, I want to be able to configure how long challenges are valid for.
  8. As a service provider, I want challenge-response items to be stored in memory to reduce unnecessary clutter in prod.

Constraints:

  1. Python programming language.
  2. FastAPI and Pydantic for user interface.
  3. smtplib with TLS for email.

Use Case

Submit Email for Verification

Main Success:

  1. User interface is executed with a properly formatted email address.
  2. A 200/OK response is provided, as well as a unique challenge ID

Extension 1: Invalid email address

  1. User interface is executed with an improperly formatted email address.
  2. A 400 response is provided with a related message.

Extension 2: AuthMail was unable to send message (SMTPConnectError | TimeoutError | SMTPSenderRefused)

  1. User interface is executed with a properly formatted email address.
  2. A 503/Service Unavailable response is provided with a message describing the issue.

Extension 3: AuthMail was unable to deliver message (SMTPDataError | SMTPRecipientsRefused)

  1. User interface is executed with a properly formatted email address.
  2. A 400/Bad Request response is provided with a message describing the issue.

Submit response for challenge

Main Success:

  1. User interface is executed with an existing challenge ID/email address pair and matching response
  2. A 200/OK response is provided

Extension 1: No such challenge

  1. User interface is executed with non-existent challenge ID/email address pair
  2. A 404/Not Found response is provided explaining that challenges expire after {} minutes

Extension 2: Invalid response

  1. User interface is executed an existing challenge ID/email address pair but without correct response
  2. A 400/Bad Request response is provided explaining that the challenge must be resubmitted

Design

UML

Latest UML

API

Create Challenge

HTTP method: POST

Endpoint path: /authmail/1/challenge/

Content type: application/json

Authorization: None

Input data:

{
  "email": "some@email.address"
}

Output data:

{
  "challenge_id": "00000000-0000-0000-0000-000000000000"
}

Submit Response

HTTP Method: POST

Endpoint path: /authmail/1/response/

Content type: application/json

Authorization: None

Input data:

{
  "challenge_id": "00000000-0000-0000-0000-000000000000",
  "email": "some@email.address",
  "response": "string response as sent to email address"
}

Output data: null

Send Email from Verified Source

HTTP Method: POST

Endpoint path: /authmail/1/msg/

Content type: application/json

Authorization: Pass the access_token returned from the PyAcct Create Session endpoint as the header token:

-H 'token: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'

Input data:

{
  "sender" : "some@email.address",
  "recipients" : [
    "some@email.address",
    "another@email.address",
    "different@email.address"
  ],
  "body" : "some_email_content"
}

Output data: null

Dependencies

This service is going to depend directly on an instance of PyAcct to send an email. The authorization workflow, however, stands on its own.