@@ -27,6 +27,7 @@ import (
2727 "code.gitea.io/gitea/modules/storage"
2828 auth_service "code.gitea.io/gitea/services/auth"
2929 "code.gitea.io/gitea/services/auth/source/oauth2"
30+ "code.gitea.io/gitea/services/auth/source/smtp"
3031 repo_service "code.gitea.io/gitea/services/repository"
3132 user_service "code.gitea.io/gitea/services/user"
3233
@@ -190,6 +191,8 @@ var (
190191 cmdAuthUpdateLdapBindDn ,
191192 cmdAuthAddLdapSimpleAuth ,
192193 cmdAuthUpdateLdapSimpleAuth ,
194+ microcmdAuthAddSMTP ,
195+ microcmdAuthUpdateSMTP ,
193196 microcmdAuthList ,
194197 microcmdAuthDelete ,
195198 },
@@ -366,6 +369,72 @@ var (
366369 },
367370 },
368371 }
372+
373+ smtpCLIFlags = []cli.Flag {
374+ cli.StringFlag {
375+ Name : "name" ,
376+ Value : "" ,
377+ Usage : "Application Name" ,
378+ },
379+ cli.StringFlag {
380+ Name : "auth-type" ,
381+ Value : "PLAIN" ,
382+ Usage : "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN" ,
383+ },
384+ cli.StringFlag {
385+ Name : "host" ,
386+ Value : "" ,
387+ Usage : "SMTP Host" ,
388+ },
389+ cli.IntFlag {
390+ Name : "port" ,
391+ Usage : "SMTP Port" ,
392+ },
393+ cli.BoolTFlag {
394+ Name : "force-smtps" ,
395+ Usage : "SMTPS is always used on port 465. Set this to force SMTPS on other ports." ,
396+ },
397+ cli.BoolTFlag {
398+ Name : "skip-verify" ,
399+ Usage : "Skip TLS verify." ,
400+ },
401+ cli.StringFlag {
402+ Name : "helo-hostname" ,
403+ Value : "" ,
404+ Usage : "Hostname sent with HELO. Leave blank to send current hostname" ,
405+ },
406+ cli.BoolTFlag {
407+ Name : "disable-helo" ,
408+ Usage : "Disable SMTP helo." ,
409+ },
410+ cli.StringFlag {
411+ Name : "allowed-domains" ,
412+ Value : "" ,
413+ Usage : "Leave empty to allow all domains. Separate multiple domains with a comma (',')" ,
414+ },
415+ cli.BoolTFlag {
416+ Name : "skip-local-2fa" ,
417+ Usage : "Skip 2FA to log on." ,
418+ },
419+ cli.BoolTFlag {
420+ Name : "active" ,
421+ Usage : "This Authentication Source is Activated." ,
422+ },
423+ }
424+
425+ microcmdAuthAddSMTP = cli.Command {
426+ Name : "add-smtp" ,
427+ Usage : "Add new SMTP authentication source" ,
428+ Action : runAddSMTP ,
429+ Flags : smtpCLIFlags ,
430+ }
431+
432+ microcmdAuthUpdateSMTP = cli.Command {
433+ Name : "update-smtp" ,
434+ Usage : "Update existing SMTP authentication source" ,
435+ Action : runUpdateSMTP ,
436+ Flags : append (smtpCLIFlags [:1 ], append ([]cli.Flag {idFlag }, smtpCLIFlags [1 :]... )... ),
437+ }
369438)
370439
371440func runChangePassword (c * cli.Context ) error {
@@ -804,6 +873,118 @@ func runUpdateOauth(c *cli.Context) error {
804873 return auth .UpdateSource (source )
805874}
806875
876+ func parseSMTPConfig (c * cli.Context , conf * smtp.Source ) error {
877+ if c .IsSet ("auth-type" ) {
878+ conf .Auth = c .String ("auth-type" )
879+ validAuthTypes := []string {"PLAIN" , "LOGIN" , "CRAM-MD5" }
880+ if ! contains (validAuthTypes , strings .ToUpper (c .String ("auth-type" ))) {
881+ return errors .New ("Auth must be one of PLAIN/LOGIN/CRAM-MD5" )
882+ }
883+ conf .Auth = c .String ("auth-type" )
884+ }
885+ if c .IsSet ("host" ) {
886+ conf .Host = c .String ("host" )
887+ }
888+ if c .IsSet ("port" ) {
889+ conf .Port = c .Int ("port" )
890+ }
891+ if c .IsSet ("allowed-domains" ) {
892+ conf .AllowedDomains = c .String ("allowed-domains" )
893+ }
894+ if c .IsSet ("force-smtps" ) {
895+ conf .ForceSMTPS = c .BoolT ("force-smtps" )
896+ }
897+ if c .IsSet ("skip-verify" ) {
898+ conf .SkipVerify = c .BoolT ("skip-verify" )
899+ }
900+ if c .IsSet ("helo-hostname" ) {
901+ conf .HeloHostname = c .String ("helo-hostname" )
902+ }
903+ if c .IsSet ("disable-helo" ) {
904+ conf .DisableHelo = c .BoolT ("disable-helo" )
905+ }
906+ if c .IsSet ("skip-local-2fa" ) {
907+ conf .SkipLocalTwoFA = c .BoolT ("skip-local-2fa" )
908+ }
909+ return nil
910+ }
911+
912+ func runAddSMTP (c * cli.Context ) error {
913+ ctx , cancel := installSignals ()
914+ defer cancel ()
915+
916+ if err := initDB (ctx ); err != nil {
917+ return err
918+ }
919+
920+ if ! c .IsSet ("name" ) || len (c .String ("name" )) == 0 {
921+ return errors .New ("name must be set" )
922+ }
923+ if ! c .IsSet ("host" ) || len (c .String ("host" )) == 0 {
924+ return errors .New ("host must be set" )
925+ }
926+ if ! c .IsSet ("port" ) {
927+ return errors .New ("port must be set" )
928+ }
929+ var active = true
930+ if c .IsSet ("active" ) {
931+ active = c .BoolT ("active" )
932+ }
933+
934+ var smtpConfig smtp.Source
935+ if err := parseSMTPConfig (c , & smtpConfig ); err != nil {
936+ return err
937+ }
938+
939+ // If not set default to PLAIN
940+ if len (smtpConfig .Auth ) == 0 {
941+ smtpConfig .Auth = "PLAIN"
942+ }
943+
944+ return auth .CreateSource (& auth.Source {
945+ Type : auth .SMTP ,
946+ Name : c .String ("name" ),
947+ IsActive : active ,
948+ Cfg : & smtpConfig ,
949+ })
950+ }
951+
952+ func runUpdateSMTP (c * cli.Context ) error {
953+ if ! c .IsSet ("id" ) {
954+ return fmt .Errorf ("--id flag is missing" )
955+ }
956+
957+ ctx , cancel := installSignals ()
958+ defer cancel ()
959+
960+ if err := initDB (ctx ); err != nil {
961+ return err
962+ }
963+
964+ source , err := auth .GetSourceByID (c .Int64 ("id" ))
965+ if err != nil {
966+ return err
967+ }
968+
969+ smtpConfig := source .Cfg .(* smtp.Source )
970+
971+ if err := parseSMTPConfig (c , smtpConfig ); err != nil {
972+ return err
973+ }
974+
975+ if c .IsSet ("name" ) {
976+ source .Name = c .String ("name" )
977+ }
978+
979+ if c .IsSet ("active" ) {
980+ source .IsActive = c .BoolT ("active" )
981+ }
982+
983+ source .Cfg = smtpConfig
984+
985+ return auth .UpdateSource (source )
986+ }
987+
807988func runListAuth (c * cli.Context ) error {
808989 ctx , cancel := installSignals ()
809990 defer cancel ()
0 commit comments