imap

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2024 License: Apache-2.0 Imports: 18 Imported by: 5

README

Venom - Executor IMAP

Use case: you have a mail server and you want to test IMAP commands ?

Venom IMAP executor implements a few IMAP commands such as FETCH, APPEND, MOVE, STORE...

How to test

Authentication
auth:
  withtls: false
  host: yourimaphost
  port: 143 # Most probably 993 if using TLS
  user: imap@venom.com
  password: imapvenompassword
Commands

As of today, these are the available commands:

  • append: create a new mail at the end of a mailbox
  • create: create a new mailbox
  • clear: delete every message in a mailbox from the mail server
  • delete: delete a message
  • fetch: retrieve a mail
  • flag: add, remove or set the flags of a mail
  • move: move a mail from one mailbox to another

Multiple commands can be stated as once: they will be executed in the order they are presented under the commands field.

Each command consists of a name field which allows to specify the command to execute. Then they are composed of the search field and/or the args field.

The search field always has the same syntax. It retrieves and returns the first mail found through the search criteria:

search:
  mailbox: testBox # The mailbox in which to search the mail
  uid: 1 # The UID to search for
  from: .*@your-domain.localhost # The "From" header field to search for
  to: you@company.tld # The "To" header field to search for
  subject: Title of mail with * # The "Subject" header field to search for
  body: .*a body content.* # The "Body" field to search for

It allows us to specify which mail the command will act upon.

⚠️ Be careful as search criteria are regular expressions. If you wish to search for special characters, don't forget to escape them:
subject: [IMPORTANT] READ THIS
subject: \[IMPORTANT\] READ THIS

Often combined to the search field, the args field allows us to specify the arguments to the command. Its syntax depends on the command.

In this section, we will describe each command syntax.

Append command

The append command creates a new mail at the end of a mailbox.

commands:
  - name: append
    args:
      mailbox: mailboxName # MANDATORY: The mailbox in which to create the mail
      from: origin-of@-my-new-mail.com # MANDATORY: the "From" header field of the new mail
      to: recipient-of@my-new-mail.com # OPTIONAL: the "To" header field of the new mail
      subject: Subject of my new mail # OPTIONAL: the "Subject" header field of the new mail
      body: Body of my new mail # OPTIONAL: the body of the new mail
      flags: # OPTIONAL: the flags of the new mail (note that the "\Recent" flag will most probably be added as well)
        - Flag1
        - Flag2
        ...
Create command

The create command creates a new mailbox.

commands:
  - name: create
    args:
      mailbox: mailboxName # MANDATORY: The name of the new mailbox to create
Clear command

The clear command deletes every message in a mailbox. It can be called in two different ways:

  • First, by listing every mailbox to clear:
commands:
  - name: clear
    args:
      mailboxes:
        - Mailbox1
        - Mailbox2
        ...
  • Second, by using the wildcard argument to clean all the existing mailboxes:
commands:
  - name: clear
    args:
      mailboxes:
        - "*"
Delete command

The delete command permanently deletes a message retrieved through the search field.

commands:
  - name: delete
    search:
      [...]
Fetch command

The fetch command retrieves a message through the search field.

commands:
  - name: fetch
    search:
      [...]
Flag command

The flag command modifies the flags of a message. It is made up of both search and args fields. The args field can be composed of up to 3 different fields:

  • add: flags to add to the mail
  • remove: flags to remove from the mail
  • set: the mail flags to set (overrides any existing flag)

All these fields can be called at once but, if specified, only set will be taken into account. They all have the same syntax.

commands:
  - name: flag
    args:
      add:
        - Flag1
        - Flag2
        ...
      remove:
        - Flag1
        - Flag2
        ...
      set:
        - Flag1
        - Flag2
        ...
Move command

The move command moves a mail from one mailbox to another. It is made up of both search and args fields.

commands:
  - name: move
    search:
      [...]
    args:
      mailbox: mailboxname # The mailbox to move the mail to
Assertions

Each execution of a command produces a result Its content depends on the command and its execution.
Taking that multiple commands can be executed in a single testcase, the result object follows this syntax:

{
  "result": {
    "commands": [
      {
        // Search represents the result of the command's search field
        "search": {
          "mailbox": "INBOX",
          "from": "from@mail-before-command-execution.com",
          "to": "to@mail-before-command-execution.com",
          "subject": "Title of mail BEFORE command execution",
          "body": "Body content of mail BEFORE command execution",
          "flags": [
            "Flag1",
            "Flag2"
          ]
        },
        // Mail represents the state of the searched mail after the command was executed
        "mail": { 
          "from": "from@mail-after-command-execution.com",
          "to": "to@mail-after-command-execution.com",
          "subject": "Title of mail AFTER command execution",
          "body": "Body content of mail AFTER command execution",
          "flags": [
            "Flag1",
            "Flag2",
            "Flag3"
          ]
        },
        "err": "Error of the command", // Err represents the command error message, supposing the command failed
        "timeseconds": 1.5 // TimeSeconds represents the duration of the command execution
      }
    ]
  }
}

Where each command has its own results that can be asserted.

As an example, here is a list of possible assertions after execution of two commands in the same testcase:

assertions:
  # First ommand
  - result.commands.commands0.err ShouldBeEmpty
  # State of the mail before command execution (search)
  - result.commands.commands0.search.from ShouldEqual "from@mail-before-command-execution.com"
  # Mail as a result of command execution
  - result.commands.commands0.mail.from ShouldEqual "to@mail-after-command-execution.com"
  # Second command
  - result.commands.commands1.err ShouldBeEmpty
  - result.commands.commands1.search.from ShouldEqual ...
  - result.commands.commands1.mail.from ShouldEqual ...
  - result.commands.commands1.mail.flags.flags0 ShouldEqual ...
  - result.commands.commands1.mail.flags.flags1 ShouldEqual ...

The commands that do not modify a mail content (headers and body) won't have the mail field filled up.
As an example, here is the typical result of a fetch, delete or move command:

{
  "result": {
    "commands": [
      {
        "search": {
          "mailbox": "INBOX",
          "from": "from@mail-before-command-execution.com",
          "to": "to@mail.com",
          "subject": "Title of retrieved mail",
          "body": "Body content of retrieved mail",
          "flags": [
            "Flag1",
            "Flag2"
          ]
        },
        "err": "",
        "timeseconds": 1.5
      }
    ]
  }
}

As another example, here is the typical result of a create or clear command:

{
  "result": {
    "commands": [
      {
        "search": {},
        "err": "",
        "timeseconds": 1.5
      }
    ]
  }
}

Testsuite example

name: IMAP testsuite
vars:
  withTLS: false
  host: localhost
  port: 1143
  user: address@example.org
  password: pass
testcases:
  - name: Clear a mailbox
    steps:
      - type: imap
        auth:
          host: "{{.host}}"
          port: "{{.port}}"
          user: "{{.user}}"
          password: "{{.password}}"
        commands:
          - name: clear
            args:
              mailboxes:
                - INBOX
        assertions:
          # As multiple commands can be executed in a single testcase, we need to specify which command result we want to assert
          - result.commands.commands0.err ShouldBeEmpty

To see more examples, check the IMAP executor test file.

Documentation

Index

Constants

View Source
const (
	// Name for test imap
	Name = "imap"
)

Variables

This section is empty.

Functions

func New

func New() venom.Executor

New returns a new Test Exec

Types

type AuthConfig added in v1.2.0

type AuthConfig struct {
	WithTLS  bool   `json:"withtls,omitempty" yaml:"withtls,omitempty"`
	Host     string `json:"host,omitempty" yaml:"host,omitempty"`
	Port     string `json:"port,omitempty" yaml:"port,omitempty"`
	User     string `json:"user,omitempty" yaml:"user,omitempty"`
	Password string `json:"password,omitempty" yaml:"password,omitempty"`
}

type Client added in v1.2.0

type Client struct {
	*imap.Client
}

type Command added in v1.2.0

type Command struct {
	// Search defines the search criteria to retrieve a mail. Some commands need to act upon a mail retrieved through Search.
	Search SearchCriteria `json:"search" yaml:"search"`
	// Name defines an IMAP command to execute.
	Name CommandName `json:"name" yaml:"name"`
	// Args defines the arguments to the command. Arguments associated to the command are listed in the README file
	Args map[string]any `json:"args" yaml:"args"`
}

Command represents a command that can be performed to messages or mailboxes.

type CommandName added in v1.2.0

type CommandName string
const (
	// CommandAppend creates a new message at the end of a specified mailbox.
	CommandAppend CommandName = "append"
	// CommandCreate creates a new mailbox.
	CommandCreate CommandName = "create"
	// CommandClear permanently removes all messages from given mailboxes.
	CommandClear CommandName = "clear"
	// CommandDelete permanently removes a message retrieved through Search field
	CommandDelete CommandName = "delete"
	// CommandFetch retrieves a mail through Search field (no args)
	CommandFetch CommandName = "fetch"
	// CommandFlag adds, removes or sets flags to a message retrieved through Search field
	CommandFlag CommandName = "flag"
	// CommandMove moves a message retrieved through Search field from one mailbox to another.
	CommandMove CommandName = "move"
)

type CommandResult added in v1.2.0

type CommandResult struct {
	// Search represents the result of the Command's search field
	Search Mail `json:"search,omitempty" yaml:"search,omitempty"`
	// Mail represents the state of the searched mail after the command was executed
	Mail        Mail    `json:"mail,omitempty" yaml:"mail,omitempty"`
	Err         string  `json:"err,omitempty" yaml:"err,omitempty"`
	TimeSeconds float64 `json:"timeseconds,omitempty" yaml:"timeseconds,omitempty"`
}

CommandResult contains the results of a command with the states of the mail before and after the command.

type Executor

type Executor struct {
	Auth     AuthConfig `json:"auth" yaml:"auth"`
	Commands []Command  `json:"commands,omitempty" yaml:"commands,omitempty"`
}

Executor represents a Test Executor

func (Executor) GetDefaultAssertions

func (Executor) GetDefaultAssertions() *venom.StepAssertions

GetDefaultAssertions return default assertions for type imap

func (Executor) Run

func (Executor) Run(ctx context.Context, step venom.TestStep) (interface{}, error)

Run execute TestStep of type exec

func (Executor) ZeroValueResult added in v0.17.0

func (Executor) ZeroValueResult() interface{}

ZeroValueResult return an empty implementation of this executor result

type Mail

type Mail struct {
	UID     uint32   `json:"uid,omitempty" yaml:"uid,omitempty"`
	From    string   `json:"from,omitempty" yaml:"from,omitempty"`
	To      string   `json:"to,omitempty" yaml:"to,omitempty"`
	Subject string   `json:"subject,omitempty" yaml:"subject,omitempty"`
	Body    string   `json:"body,omitempty" yaml:"body,omitempty"`
	Flags   []string `json:"flags,omitempty" yaml:"flags,omitempty"`
}

type Result

type Result struct {
	Commands []CommandResult `json:"commands,omitempty" yaml:"commands,omitempty"`
}

Result represents a step result. It contains the results of every command that was executed

type SearchCriteria added in v1.2.0

type SearchCriteria struct {
	Mailbox string `json:"mailbox,omitempty" yaml:"mailbox,omitempty"`
	UID     uint32 `json:"uid,omitempty" yaml:"uid,omitempty"`
	From    string `json:"from,omitempty" yaml:"from,omitempty"`
	To      string `json:"to,omitempty" yaml:"to,omitempty"`
	Subject string `json:"subject,omitempty" yaml:"subject,omitempty"`
	Body    string `json:"body,omitempty" yaml:"body,omitempty"`
}

SearchCriteria represents the search criteria to fetch mails through FETCH command (https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL