diff --git a/services/reports/src/config.rs b/services/reports/src/config.rs
--- a/services/reports/src/config.rs
+++ b/services/reports/src/config.rs
@@ -2,9 +2,11 @@
 use clap::Parser;
 use comm_services_lib::blob::client::Url;
 use once_cell::sync::Lazy;
-use tracing::info;
+use tracing::{info, warn};
 
-// environment variabl names
+use crate::email::config::{EmailArgs, EmailConfig};
+
+// environment variable names
 const ENV_LOCALSTACK_ENDPOINT: &str = "LOCALSTACK_ENDPOINT";
 const ENV_BLOB_SERVICE_URL: &str = "BLOB_SERVICE_URL";
 
@@ -21,12 +23,23 @@
   #[arg(env = ENV_LOCALSTACK_ENDPOINT)]
   #[arg(long)]
   localstack_endpoint: Option<String>,
+
+  /// This config shouldn't be used directly. It's used for parsing purposes
+  /// only. Use [`AppConfig::email_config()`] instead.
+  #[command(flatten)]
+  email_args: EmailArgs,
 }
 
 impl AppConfig {
   pub fn is_dev(&self) -> bool {
     self.localstack_endpoint.is_some()
   }
+
+  pub fn email_config(&self) -> Option<EmailConfig> {
+    // we return None in case of error because this should've already been
+    // checked by parse_cmdline_args()
+    self.email_args.parse().ok().flatten()
+  }
 }
 
 /// Stores configuration parsed from command-line arguments
@@ -37,7 +50,19 @@
 /// Should be called at the beginning of the `main()` function.
 pub(super) fn parse_cmdline_args() -> Result<&'static AppConfig> {
   // force evaluation of the lazy initialized config
-  Ok(Lazy::force(&CONFIG))
+  let cfg = Lazy::force(&CONFIG);
+
+  // initialize e-mail config to check for errors
+  match cfg.email_args.parse()? {
+    Some(_) => {
+      info!("E-mail config found. E-mail notifications are enabled.");
+    }
+    None => {
+      warn!("E-mail config is disabled or missing! E-mails will not be sent.");
+    }
+  }
+
+  Ok(cfg)
 }
 
 /// Provides region/credentials configuration for AWS SDKs
diff --git a/services/reports/src/main.rs b/services/reports/src/main.rs
--- a/services/reports/src/main.rs
+++ b/services/reports/src/main.rs
@@ -31,10 +31,11 @@
   configure_logging()?;
   let cfg = config::parse_cmdline_args()?;
   let aws_config = config::load_aws_config().await;
+  let email_config = cfg.email_config();
 
   let db = database::client::DatabaseClient::new(&aws_config);
   let blob_client = BlobServiceClient::new(cfg.blob_service_url.clone());
-  let service = ReportsService::new(db, blob_client);
+  let service = ReportsService::new(db, blob_client, email_config);
 
   crate::http::run_http_server(service).await
 }
diff --git a/services/reports/src/service.rs b/services/reports/src/service.rs
--- a/services/reports/src/service.rs
+++ b/services/reports/src/service.rs
@@ -8,6 +8,7 @@
 use std::{
   collections::HashMap,
   future::{ready, Ready},
+  sync::Arc,
 };
 use tracing::error;
 
@@ -16,6 +17,7 @@
     client::{DatabaseClient, ReportsPage},
     item::ReportItem,
   },
+  email::config::EmailConfig,
   report_types::{ReportID, ReportInput, ReportOutput, ReportType},
 };
 
@@ -46,14 +48,20 @@
   db: DatabaseClient,
   blob_client: BlobServiceClient,
   requesting_user_id: Option<String>,
+  email_config: Option<Arc<EmailConfig>>,
 }
 
 impl ReportsService {
-  pub fn new(db: DatabaseClient, blob_client: BlobServiceClient) -> Self {
+  pub fn new(
+    db: DatabaseClient,
+    blob_client: BlobServiceClient,
+    email_config: Option<EmailConfig>,
+  ) -> Self {
     Self {
       db,
       blob_client,
       requesting_user_id: None,
+      email_config: email_config.map(Arc::new),
     }
   }
 
@@ -61,6 +69,7 @@
     let user_id = user.user_id.to_string();
     Self {
       db: self.db.clone(),
+      email_config: self.email_config.clone(),
       blob_client: self.blob_client.with_user_identity(user),
       requesting_user_id: Some(user_id),
     }