Skip to content

_email

EmailSettings

Bases: BaseSettings

Class with settings for email-sending feature.

ATTRIBUTE DESCRIPTION
FRACTAL_EMAIL_SENDER

Address of the OAuth-signup email sender.

TYPE: EmailStr | None

FRACTAL_EMAIL_PASSWORD

Password for the OAuth-signup email sender.

TYPE: SecretStr | None

FRACTAL_EMAIL_SMTP_SERVER

SMTP server for the OAuth-signup emails.

TYPE: str | None

FRACTAL_EMAIL_SMTP_PORT

SMTP server port for the OAuth-signup emails.

TYPE: int | None

FRACTAL_EMAIL_INSTANCE_NAME

Fractal instance name, to be included in the OAuth-signup emails.

TYPE: str | None

FRACTAL_EMAIL_RECIPIENTS

Comma-separated list of recipients of the OAuth-signup emails.

TYPE: str | None

FRACTAL_EMAIL_USE_STARTTLS

Whether to use StartTLS when using the SMTP server.

TYPE: Literal['true', 'false']

FRACTAL_EMAIL_USE_LOGIN

Whether to use login when using the SMTP server. If 'true', FRACTAL_EMAIL_PASSWORD must be provided.

TYPE: Literal['true', 'false']

Source code in fractal_server/config/_email.py
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
class EmailSettings(BaseSettings):
    """
    Class with settings for email-sending feature.

    Attributes:
        FRACTAL_EMAIL_SENDER:
            Address of the OAuth-signup email sender.
        FRACTAL_EMAIL_PASSWORD:
            Password for the OAuth-signup email sender.
        FRACTAL_EMAIL_SMTP_SERVER:
            SMTP server for the OAuth-signup emails.
        FRACTAL_EMAIL_SMTP_PORT:
            SMTP server port for the OAuth-signup emails.
        FRACTAL_EMAIL_INSTANCE_NAME:
            Fractal instance name, to be included in the OAuth-signup emails.
        FRACTAL_EMAIL_RECIPIENTS:
            Comma-separated list of recipients of the OAuth-signup emails.
        FRACTAL_EMAIL_USE_STARTTLS:
            Whether to use StartTLS when using the SMTP server.
        FRACTAL_EMAIL_USE_LOGIN:
            Whether to use login when using the SMTP server.
            If 'true', FRACTAL_EMAIL_PASSWORD  must be provided.
    """

    model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)

    FRACTAL_EMAIL_SENDER: EmailStr | None = None
    FRACTAL_EMAIL_PASSWORD: SecretStr | None = None
    FRACTAL_EMAIL_SMTP_SERVER: str | None = None
    FRACTAL_EMAIL_SMTP_PORT: int | None = None
    FRACTAL_EMAIL_INSTANCE_NAME: str | None = None
    FRACTAL_EMAIL_RECIPIENTS: str | None = None
    FRACTAL_EMAIL_USE_STARTTLS: Literal["true", "false"] = "true"
    FRACTAL_EMAIL_USE_LOGIN: Literal["true", "false"] = "true"

    public: PublicEmailSettings | None = None
    """
    The validated field which is actually used in `fractal-server`,
    automatically populated upon creation.
    """

    @model_validator(mode="after")
    def validate_email_settings(self: Self) -> Self:
        """
        Set `self.public`.
        """

        email_values = [
            self.FRACTAL_EMAIL_SENDER,
            self.FRACTAL_EMAIL_SMTP_SERVER,
            self.FRACTAL_EMAIL_SMTP_PORT,
            self.FRACTAL_EMAIL_INSTANCE_NAME,
            self.FRACTAL_EMAIL_RECIPIENTS,
        ]
        if len(set(email_values)) == 1:
            # All required EMAIL attributes are None
            pass
        elif None in email_values:
            # Not all required EMAIL attributes are set
            error_msg = (
                "Invalid FRACTAL_EMAIL configuration. "
                f"Given values: {email_values}."
            )
            raise ValueError(error_msg)
        else:
            use_starttls = self.FRACTAL_EMAIL_USE_STARTTLS == "true"
            use_login = self.FRACTAL_EMAIL_USE_LOGIN == "true"

            if use_login and self.FRACTAL_EMAIL_PASSWORD is None:
                raise ValueError(
                    "'FRACTAL_EMAIL_USE_LOGIN' is 'true' but "
                    "'FRACTAL_EMAIL_PASSWORD' is not provided."
                )

            self.public = PublicEmailSettings(
                sender=self.FRACTAL_EMAIL_SENDER,
                recipients=self.FRACTAL_EMAIL_RECIPIENTS.split(","),
                smtp_server=self.FRACTAL_EMAIL_SMTP_SERVER,
                port=self.FRACTAL_EMAIL_SMTP_PORT,
                password=self.FRACTAL_EMAIL_PASSWORD,
                instance_name=self.FRACTAL_EMAIL_INSTANCE_NAME,
                use_starttls=use_starttls,
                use_login=use_login,
            )

        return self

public = None class-attribute instance-attribute

The validated field which is actually used in fractal-server, automatically populated upon creation.

validate_email_settings()

Set self.public.

Source code in fractal_server/config/_email.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
@model_validator(mode="after")
def validate_email_settings(self: Self) -> Self:
    """
    Set `self.public`.
    """

    email_values = [
        self.FRACTAL_EMAIL_SENDER,
        self.FRACTAL_EMAIL_SMTP_SERVER,
        self.FRACTAL_EMAIL_SMTP_PORT,
        self.FRACTAL_EMAIL_INSTANCE_NAME,
        self.FRACTAL_EMAIL_RECIPIENTS,
    ]
    if len(set(email_values)) == 1:
        # All required EMAIL attributes are None
        pass
    elif None in email_values:
        # Not all required EMAIL attributes are set
        error_msg = (
            "Invalid FRACTAL_EMAIL configuration. "
            f"Given values: {email_values}."
        )
        raise ValueError(error_msg)
    else:
        use_starttls = self.FRACTAL_EMAIL_USE_STARTTLS == "true"
        use_login = self.FRACTAL_EMAIL_USE_LOGIN == "true"

        if use_login and self.FRACTAL_EMAIL_PASSWORD is None:
            raise ValueError(
                "'FRACTAL_EMAIL_USE_LOGIN' is 'true' but "
                "'FRACTAL_EMAIL_PASSWORD' is not provided."
            )

        self.public = PublicEmailSettings(
            sender=self.FRACTAL_EMAIL_SENDER,
            recipients=self.FRACTAL_EMAIL_RECIPIENTS.split(","),
            smtp_server=self.FRACTAL_EMAIL_SMTP_SERVER,
            port=self.FRACTAL_EMAIL_SMTP_PORT,
            password=self.FRACTAL_EMAIL_PASSWORD,
            instance_name=self.FRACTAL_EMAIL_INSTANCE_NAME,
            use_starttls=use_starttls,
            use_login=use_login,
        )

    return self

PublicEmailSettings

Bases: BaseModel

Schema for EmailSettings.public, namely the ready-to-use settings.

ATTRIBUTE DESCRIPTION
sender

Sender email address.

TYPE: EmailStr

recipients

List of recipients email address.

TYPE: list[EmailStr]

smtp_server

SMTP server address.

TYPE: str

port

SMTP server port.

TYPE: int

password

Sender password.

TYPE: SecretStr | None

instance_name

Name of SMTP server instance.

TYPE: str

use_starttls

Whether to use the security protocol.

TYPE: bool

use_login

Whether to use login.

TYPE: bool

Source code in fractal_server/config/_email.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class PublicEmailSettings(BaseModel):
    """
    Schema for `EmailSettings.public`, namely the ready-to-use settings.

    Attributes:
        sender: Sender email address.
        recipients: List of recipients email address.
        smtp_server: SMTP server address.
        port: SMTP server port.
        password: Sender password.
        instance_name: Name of SMTP server instance.
        use_starttls: Whether to use the security protocol.
        use_login: Whether to use login.
    """

    sender: EmailStr
    recipients: list[EmailStr] = Field(min_length=1)
    smtp_server: str
    port: int
    password: SecretStr | None = None
    instance_name: str
    use_starttls: bool
    use_login: bool

    @property
    def password_not_none(self: Self) -> SecretStr:
        if self.password is None:
            raise RuntimeError("password=None in password_not_none method.")
        else:
            return self.password