16
16
17
17
use std:: collections:: HashMap ;
18
18
use std:: str:: FromStr ;
19
- use tracing:: info;
19
+ use tracing:: { info, warn } ;
20
20
21
21
#[ derive( Debug , Clone , PartialEq ) ]
22
22
pub enum MailerType {
@@ -37,7 +37,6 @@ impl FromStr for MailerType {
37
37
}
38
38
39
39
const DEFAULT_MAILER_TYPE : & str = "sendgrid" ;
40
- const DEFAULT_MAILER_API_HOST : & str = "" ; // Optional
41
40
const DEFAULT_MAILER_API_KEY : & str = "" ;
42
41
const DEFAULT_MAILER_FROM_EMAIL : & str = "no-reply@example.com" ;
43
42
const DEFAULT_MAILER_FROM_NAME : & str = "Heima Verify" ;
@@ -63,12 +62,29 @@ const DEFAULT_ENTRY_POINT_ADDRESS: &str = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026
63
62
const DEFAULT_WILDMETA_API_URL : & str = "https://test-dex-api.heima.network" ;
64
63
65
64
#[ derive( Debug , Clone ) ]
66
- pub struct ConfigLoader {
65
+ pub struct MailerConfig {
67
66
pub mailer_type : MailerType ,
68
67
pub mailer_api_host : Option < String > ,
69
68
pub mailer_api_key : String ,
70
69
pub mailer_from_email : String ,
71
70
pub mailer_from_name : String ,
71
+ }
72
+
73
+ impl Default for MailerConfig {
74
+ fn default ( ) -> Self {
75
+ Self {
76
+ mailer_type : MailerType :: from_str ( DEFAULT_MAILER_TYPE ) . unwrap_or ( MailerType :: Sendgrid ) ,
77
+ mailer_api_host : None ,
78
+ mailer_api_key : DEFAULT_MAILER_API_KEY . to_string ( ) ,
79
+ mailer_from_email : DEFAULT_MAILER_FROM_EMAIL . to_string ( ) ,
80
+ mailer_from_name : DEFAULT_MAILER_FROM_NAME . to_string ( ) ,
81
+ }
82
+ }
83
+ }
84
+
85
+ #[ derive( Debug , Clone ) ]
86
+ pub struct ConfigLoader {
87
+ pub mailer_configs : HashMap < String , MailerConfig > ,
72
88
pub google_client_id : String ,
73
89
pub google_client_secret : String ,
74
90
pub parentchain_url : String ,
@@ -115,51 +131,6 @@ impl ConfigLoader {
115
131
info ! ( "Executing: {}" , std:: env:: args( ) . collect:: <Vec <_>>( ) . join( " " ) ) ;
116
132
117
133
let vars: HashMap < & str , EnvVar > = HashMap :: from ( [
118
- (
119
- "mailer_type" ,
120
- EnvVar {
121
- env_key : "OE_MAILER_TYPE" ,
122
- default : DEFAULT_MAILER_TYPE ,
123
- sensitive : false ,
124
- optional : false ,
125
- } ,
126
- ) ,
127
- (
128
- "mailer_api_host" ,
129
- EnvVar {
130
- env_key : "OE_SENDGRID_API_HOST" ,
131
- default : DEFAULT_MAILER_API_HOST ,
132
- sensitive : false ,
133
- optional : true ,
134
- } ,
135
- ) ,
136
- (
137
- "mailer_api_key" ,
138
- EnvVar {
139
- env_key : "OE_SENDGRID_API_KEY" ,
140
- default : DEFAULT_MAILER_API_KEY ,
141
- sensitive : true ,
142
- optional : false ,
143
- } ,
144
- ) ,
145
- (
146
- "mailer_from_email" ,
147
- EnvVar {
148
- env_key : "OE_SENDGRID_FROM_EMAIL" ,
149
- default : DEFAULT_MAILER_FROM_EMAIL ,
150
- sensitive : false ,
151
- optional : false ,
152
- } ,
153
- ) ,
154
- (
155
- "mailer_from_name" ,
156
- EnvVar {
157
- env_key : "OE_SENDGRID_FROM_NAME" ,
158
- default : DEFAULT_MAILER_FROM_NAME ,
159
- sensitive : false ,
160
- optional : false ,
161
- } ,
162
- ) ,
163
134
(
164
135
"google_client_id" ,
165
136
EnvVar {
@@ -354,12 +325,10 @@ impl ConfigLoader {
354
325
let get = |key : & str | get_env_value ( & vars[ key] ) . unwrap_or_default ( ) ;
355
326
let get_opt = |key : & str | get_env_value ( & vars[ key] ) ;
356
327
328
+ let mailer_configs = Self :: load_mailer_configs ( ) ;
329
+
357
330
ConfigLoader {
358
- mailer_type : MailerType :: from_str ( & get ( "mailer_type" ) ) . unwrap_or ( MailerType :: Sendgrid ) ,
359
- mailer_api_host : get_opt ( "mailer_api_host" ) ,
360
- mailer_api_key : get ( "mailer_api_key" ) ,
361
- mailer_from_email : get ( "mailer_from_email" ) ,
362
- mailer_from_name : get ( "mailer_from_name" ) ,
331
+ mailer_configs,
363
332
google_client_id : get ( "google_client_id" ) ,
364
333
google_client_secret : get ( "google_client_secret" ) ,
365
334
parentchain_url : get ( "parentchain_url" ) ,
@@ -382,4 +351,93 @@ impl ConfigLoader {
382
351
wildmeta_api_url : get ( "wildmeta_api_url" ) ,
383
352
}
384
353
}
354
+
355
+ /// Load mailer configurations for multiple clients from environment variables
356
+ /// Format: OE_MAILER_TYPE_{CLIENT}, OE_MAILER_API_HOST_{CLIENT}, etc.
357
+ /// CLIENT can be HEIMA, WILDMETA, CONSOLE, etc.
358
+ fn load_mailer_configs ( ) -> HashMap < String , MailerConfig > {
359
+ let mut configs = HashMap :: new ( ) ;
360
+
361
+ // Get all environment variables
362
+ let env_vars: HashMap < String , String > = std:: env:: vars ( ) . collect ( ) ;
363
+
364
+ // Find all unique client suffixes
365
+ let mut clients = std:: collections:: HashSet :: new ( ) ;
366
+ for key in env_vars. keys ( ) {
367
+ if key. starts_with ( "OE_MAILER_TYPE_" ) {
368
+ // Extract client name from OE_MAILER_TYPE_{CLIENT}
369
+ if let Some ( client) = key. strip_prefix ( "OE_MAILER_TYPE_" ) {
370
+ info ! ( "Found mailer type configuration for client: {}" , client) ;
371
+ clients. insert ( client. to_lowercase ( ) ) ;
372
+ }
373
+ }
374
+ }
375
+
376
+ info ! ( "Total discovered clients: {:?}" , clients) ;
377
+
378
+ // If no clients are configured via environment variables, provide default console fallback
379
+ if clients. is_empty ( ) {
380
+ warn ! ( "No mailer configurations found in environment variables. Adding default console mailer." ) ;
381
+ let default_config = MailerConfig {
382
+ mailer_type : MailerType :: Console ,
383
+ mailer_api_host : None ,
384
+ mailer_api_key : String :: new ( ) ,
385
+ mailer_from_email : "test@example.com" . to_string ( ) ,
386
+ mailer_from_name : "Default Console Mailer" . to_string ( ) ,
387
+ } ;
388
+ configs. insert ( "console" . to_string ( ) , default_config) ;
389
+ return configs;
390
+ }
391
+
392
+ // Load configuration for each client
393
+ for client in clients {
394
+ let client_upper = client. to_uppercase ( ) ;
395
+ let mut config = MailerConfig :: default ( ) ;
396
+
397
+ // Load client-specific values, falling back to defaults
398
+ if let Ok ( mailer_type) = std:: env:: var ( format ! ( "OE_MAILER_TYPE_{}" , client_upper) ) {
399
+ config. mailer_type =
400
+ MailerType :: from_str ( & mailer_type) . unwrap_or ( config. mailer_type ) ;
401
+ }
402
+
403
+ if let Ok ( api_host) = std:: env:: var ( format ! ( "OE_MAILER_API_HOST_{}" , client_upper) ) {
404
+ config. mailer_api_host = if api_host. is_empty ( ) { None } else { Some ( api_host) } ;
405
+ }
406
+
407
+ if let Ok ( api_key) = std:: env:: var ( format ! ( "OE_MAILER_API_KEY_{}" , client_upper) ) {
408
+ config. mailer_api_key = api_key;
409
+ }
410
+
411
+ if let Ok ( from_email) = std:: env:: var ( format ! ( "OE_MAILER_FROM_EMAIL_{}" , client_upper) )
412
+ {
413
+ config. mailer_from_email = from_email;
414
+ }
415
+
416
+ if let Ok ( from_name) = std:: env:: var ( format ! ( "OE_MAILER_FROM_NAME_{}" , client_upper) ) {
417
+ config. mailer_from_name = from_name;
418
+ }
419
+
420
+ info ! (
421
+ "Loaded mailer config for client '{}': type={:?}, from_email={}" ,
422
+ client, config. mailer_type, config. mailer_from_email
423
+ ) ;
424
+
425
+ configs. insert ( client. clone ( ) , config) ;
426
+ }
427
+
428
+ configs
429
+ }
430
+
431
+ /// Get mailer configuration for a specific client
432
+ pub fn get_mailer_config ( & self , client_id : & str ) -> Option < MailerConfig > {
433
+ let client_key = client_id. to_lowercase ( ) ;
434
+ self . mailer_configs . get ( & client_key) . cloned ( )
435
+ }
436
+
437
+ /// Get all available client configurations
438
+ pub fn list_available_clients ( & self ) -> Vec < String > {
439
+ let mut clients: Vec < String > = self . mailer_configs . keys ( ) . cloned ( ) . collect ( ) ;
440
+ clients. sort ( ) ;
441
+ clients
442
+ }
385
443
}
0 commit comments