repo_description: Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD
repo_topics: bitbucket cicd devops docker-registry-v2 git git-gui git-lfs git-server gitea github github-actions gitlab go golang hacktoberfest maven-server npm-registry self-hosted typescript vue
code: // Copyright 2025 The Gitea Authors. All rights reserved.
  // SPDX-License-Identifier: MIT
  
  package cmd
  
  import (
  	"context"
  	"testing"
  
  	auth_model "code.gitea.io/gitea/models/auth"
  	"code.gitea.io/gitea/services/auth/source/smtp"
  
  	"github.com/stretchr/testify/assert"
  	"github.com/urfave/cli/v3"
  )
  
  func TestAddSMTP(t *testing.T) {
  	testCases := []struct {
  		name   string
  		args   []string
  		source *auth_model.Source
  		errMsg string
  	}{
  		{
  			name: "missing name",
  			args: []string{
  				"--host", "localhost",
  				"--port", "25",
  			},
  			errMsg: "name must be set",
  		},
  		{
  			name: "missing host",
  			args: []string{
  				"--name", "test",
  				"--port", "25",
  			},
  			errMsg: "host must be set",
  		},
  		{
  			name: "missing port",
  			args: []string{
  				"--name", "test",
  				"--host", "localhost",
  			},
  			errMsg: "port must be set",
  		},
  		{
  			name: "valid config",
  			args: []string{
  				"--name", "test",
  				"--host", "localhost",
  				"--port", "25",
  			},
  			source: &auth_model.Source{
  				Type:     auth_model.SMTP,
  				Name:     "test",
  				IsActive: true,
  				Cfg: &smtp.Source{
  					Auth: "PLAIN",
  					Host: "localhost",
  					Port: 25,
  				},
  				TwoFactorPolicy: "",
  			},
  		},
  		{
  			name: "valid config with options",
  			args: []string{
  				"--name", "test",
  				"--host", "localhost",
  				"--port", "25",
  				"--auth-type", "LOGIN",
  				"--force-smtps",
  				"--skip-verify",
  				"--helo-hostname", "example.com",
  				"--disable-helo=true",
  				"--allowed-domains", "example.com,example.org",
  				"--skip-local-2fa",
  				"--active=false",
  			},
  			source: &auth_model.Source{
  				Type:     auth_model.SMTP,
  				Name:     "test",
  				IsActive: false,
  				Cfg: &smtp.Source{
  					Auth:           "LOGIN",
  					Host:           "localhost",
  					Port:           25,
  					ForceSMTPS:     true,
  					SkipVerify:     true,
  					HeloHostname:   "example.com",
  					DisableHelo:    true,
  					AllowedDomains: "example.com,example.org",
  				},
  				TwoFactorPolicy: "skip",
  			},
  		},
  	}
  
  	for _, tc := range testCases {
  		t.Run(tc.name, func(t *testing.T) {
  			a := &authService{
  				initDB: func(ctx context.Context) error {
  					return nil
  				},
  				createAuthSource: func(ctx context.Context, source *auth_model.Source) error {
  					assert.Equal(t, tc.source, source)
  					return nil
  				},
  			}
  
  			cmd := &cli.Command{
  				Flags:  microcmdAuthAddSMTP().Flags,
  				Action: a.runAddSMTP,
  			}
  
  			args := []string{"smtp-test"}
  			args = append(args, tc.args...)
  
  			t.Log(args)
  			err := cmd.Run(t.Context(), args)
  
  			if tc.errMsg != "" {
  				assert.EqualError(t, err, tc.errMsg)
  			} else {
  				assert.NoError(t, err)
  			}
  		})
  	}
  }
  
  func TestUpdateSMTP(t *testing.T) {
  	testCases := []struct {
  		name               string
  		args               []string
  		existingAuthSource *auth_model.Source
  		authSource         *auth_model.Source
  		errMsg             string
  	}{
  		{
  			name: "missing id",
  			args: []string{
  				"--name", "test",
  				"--host", "localhost",
  				"--port", "25",
  			},
  			errMsg: "--id flag is missing",
  		},
  		{
  			name: "valid config",
  			existingAuthSource: &auth_model.Source{
  				ID:       1,
  				Type:     auth_model.SMTP,
  				Name:     "old name",
  				IsActive: true,
  				Cfg: &smtp.Source{
  					Auth: "PLAIN",
  					Host: "old host",
  					Port: 26,
  				},
  			},
  			args: []string{
  				"--id", "1",
  				"--name", "test",
  				"--host", "localhost",
  				"--port", "25",
  			},
  			authSource: &auth_model.Source{
  				ID:       1,
  				Type:     auth_model.SMTP,
  				Name:     "test",
  				IsActive: true,
  				Cfg: &smtp.Source{
  					Auth: "PLAIN",
  					Host: "localhost",
  					Port: 25,
  				},
  			},
  		},
  		{
  			name: "valid config with options",
  			existingAuthSource: &auth_model.Source{
  				ID:       1,
  				Type:     auth_model.SMTP,
  				Name:     "old name",
  				IsActive: true,
  				Cfg: &smtp.Source{
  					Auth:           "PLAIN",
  					Host:           "old host",
  					Port:           26,
  					HeloHostname:   "old.example.com",
  					AllowedDomains: "old.example.com",
  				},
  				TwoFactorPolicy: "",
  			},
  			args: []string{
  				"--id", "1",
  				"--name", "test",
  				"--host", "localhost",
  				"--port", "25",
  				"--auth-type", "LOGIN",
  				"--force-smtps",
  				"--skip-verify",
  				"--helo-hostname", "example.com",
  				"--disable-helo",
  				"--allowed-domains", "example.com,example.org",
  				"--skip-local-2fa",
  				"--active=false",
  			},
  			authSource: &auth_model.Source{
  				ID:       1,
  				Type:     auth_model.SMTP,
  				Name:     "test",
  				IsActive: false,
  				Cfg: &smtp.Source{
  					Auth:           "LOGIN",
  					Host:           "localhost",
  					Port:           25,
  					ForceSMTPS:     true,
  					SkipVerify:     true,
  					HeloHostname:   "example.com",
  					DisableHelo:    true,
  					AllowedDomains: "example.com,example.org",
  				},
  				TwoFactorPolicy: "skip",
  			},
  		},
  	}
  
  	for _, tc := range testCases {
  		t.Run(tc.name, func(t *testing.T) {
  			a := &authService{
  				initDB: func(ctx context.Context) error {
  					return nil
  				},
  				getAuthSourceByID: func(ctx context.Context, id int64) (*auth_model.Source, error) {
  					return &auth_model.Source{
  						ID:       1,
  						Type:     auth_model.SMTP,
  						Name:     "test",
  						IsActive: true,
  						Cfg: &smtp.Source{
  							Auth: "PLAIN",
  						},
  					}, nil
  				},
  
  				updateAuthSource: func(ctx context.Context, source *auth_model.Source) error {
  					assert.Equal(t, tc.authSource, source)
  					return nil
  				},
  			}
  
  			app := &cli.Command{
  				Flags:  microcmdAuthUpdateSMTP().Flags,
  				Action: a.runUpdateSMTP,
  			}
  			args := []string{"smtp-tests"}
  			args = append(args, tc.args...)
  
  			err := app.Run(t.Context(), args)
  
  			if tc.errMsg != "" {
  				assert.EqualError(t, err, tc.errMsg)
  			} else {
  				assert.NoError(t, err)
  			}
  		})
  	}
  }
  