github.com/gophish/gophish@v0.12.2-0.20230915144530-8e7929441393/models/imap.go (about)

     1  package models
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  	"time"
     7  
     8  	log "github.com/gophish/gophish/logger"
     9  )
    10  
    11  const DefaultIMAPFolder = "INBOX"
    12  const DefaultIMAPFreq = 60 // Every 60 seconds
    13  
    14  // IMAP contains the attributes needed to handle logging into an IMAP server to check
    15  // for reported emails
    16  type IMAP struct {
    17  	UserId                      int64     `json:"-" gorm:"column:user_id"`
    18  	Enabled                     bool      `json:"enabled"`
    19  	Host                        string    `json:"host"`
    20  	Port                        uint16    `json:"port,string,omitempty"`
    21  	Username                    string    `json:"username"`
    22  	Password                    string    `json:"password"`
    23  	TLS                         bool      `json:"tls"`
    24  	IgnoreCertErrors            bool      `json:"ignore_cert_errors"`
    25  	Folder                      string    `json:"folder"`
    26  	RestrictDomain              string    `json:"restrict_domain"`
    27  	DeleteReportedCampaignEmail bool      `json:"delete_reported_campaign_email"`
    28  	LastLogin                   time.Time `json:"last_login,omitempty"`
    29  	ModifiedDate                time.Time `json:"modified_date"`
    30  	IMAPFreq                    uint32    `json:"imap_freq,string,omitempty"`
    31  }
    32  
    33  // ErrIMAPHostNotSpecified is thrown when there is no Host specified
    34  // in the IMAP configuration
    35  var ErrIMAPHostNotSpecified = errors.New("No IMAP Host specified")
    36  
    37  // ErrIMAPPortNotSpecified is thrown when there is no Port specified
    38  // in the IMAP configuration
    39  var ErrIMAPPortNotSpecified = errors.New("No IMAP Port specified")
    40  
    41  // ErrInvalidIMAPHost indicates that the IMAP server string is invalid
    42  var ErrInvalidIMAPHost = errors.New("Invalid IMAP server address")
    43  
    44  // ErrInvalidIMAPPort indicates that the IMAP Port is invalid
    45  var ErrInvalidIMAPPort = errors.New("Invalid IMAP Port")
    46  
    47  // ErrIMAPUsernameNotSpecified is thrown when there is no Username specified
    48  // in the IMAP configuration
    49  var ErrIMAPUsernameNotSpecified = errors.New("No Username specified")
    50  
    51  // ErrIMAPPasswordNotSpecified is thrown when there is no Password specified
    52  // in the IMAP configuration
    53  var ErrIMAPPasswordNotSpecified = errors.New("No Password specified")
    54  
    55  // ErrInvalidIMAPFreq is thrown when the frequency for polling the
    56  // IMAP server is invalid
    57  var ErrInvalidIMAPFreq = errors.New("Invalid polling frequency")
    58  
    59  // TableName specifies the database tablename for Gorm to use
    60  func (im IMAP) TableName() string {
    61  	return "imap"
    62  }
    63  
    64  // Validate ensures that IMAP configs/connections are valid
    65  func (im *IMAP) Validate() error {
    66  	switch {
    67  	case im.Host == "":
    68  		return ErrIMAPHostNotSpecified
    69  	case im.Port == 0:
    70  		return ErrIMAPPortNotSpecified
    71  	case im.Username == "":
    72  		return ErrIMAPUsernameNotSpecified
    73  	case im.Password == "":
    74  		return ErrIMAPPasswordNotSpecified
    75  	}
    76  
    77  	// Set the default value for Folder
    78  	if im.Folder == "" {
    79  		im.Folder = DefaultIMAPFolder
    80  	}
    81  
    82  	// Make sure im.Host is an IP or hostname. NB will fail if unable to resolve the hostname.
    83  	ip := net.ParseIP(im.Host)
    84  	_, err := net.LookupHost(im.Host)
    85  	if ip == nil && err != nil {
    86  		return ErrInvalidIMAPHost
    87  	}
    88  
    89  	// Make sure 1 >= port <= 65535
    90  	if im.Port < 1 || im.Port > 65535 {
    91  		return ErrInvalidIMAPPort
    92  	}
    93  
    94  	// Make sure the polling frequency is between every 30 seconds and every year
    95  	// If not set it to the default
    96  	if im.IMAPFreq < 30 || im.IMAPFreq > 31540000 {
    97  		im.IMAPFreq = DefaultIMAPFreq
    98  	}
    99  
   100  	return nil
   101  }
   102  
   103  // GetIMAP returns the IMAP server owned by the given user.
   104  func GetIMAP(uid int64) ([]IMAP, error) {
   105  	im := []IMAP{}
   106  	count := 0
   107  	err := db.Where("user_id=?", uid).Find(&im).Count(&count).Error
   108  
   109  	if err != nil {
   110  		log.Error(err)
   111  		return im, err
   112  	}
   113  	return im, nil
   114  }
   115  
   116  // PostIMAP updates IMAP settings for a user in the database.
   117  func PostIMAP(im *IMAP, uid int64) error {
   118  	err := im.Validate()
   119  	if err != nil {
   120  		log.Error(err)
   121  		return err
   122  	}
   123  
   124  	// Delete old entry. TODO: Save settings and if fails to Save below replace with original
   125  	err = DeleteIMAP(uid)
   126  	if err != nil {
   127  		log.Error(err)
   128  		return err
   129  	}
   130  
   131  	// Insert new settings into the DB
   132  	err = db.Save(im).Error
   133  	if err != nil {
   134  		log.Error("Unable to save to database: ", err.Error())
   135  	}
   136  	return err
   137  }
   138  
   139  // DeleteIMAP deletes the existing IMAP in the database.
   140  func DeleteIMAP(uid int64) error {
   141  	err := db.Where("user_id=?", uid).Delete(&IMAP{}).Error
   142  	if err != nil {
   143  		log.Error(err)
   144  	}
   145  	return err
   146  }
   147  
   148  func SuccessfulLogin(im *IMAP) error {
   149  	err := db.Model(&im).Where("user_id = ?", im.UserId).Update("last_login", time.Now().UTC()).Error
   150  	if err != nil {
   151  		log.Error("Unable to update database: ", err.Error())
   152  	}
   153  	return err
   154  }