|
1 | 1 | package client |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "compress/flate" |
4 | 5 | "errors" |
| 6 | + "net" |
5 | 7 |
|
6 | 8 | "github.com/emersion/go-imap" |
7 | 9 | "github.com/emersion/go-imap/commands" |
| 10 | + "github.com/emersion/go-imap/internal" |
8 | 11 | ) |
9 | 12 |
|
10 | 13 | // ErrAlreadyLoggedOut is returned if Logout is called when the client is |
11 | 14 | // already logged out. |
12 | 15 | var ErrAlreadyLoggedOut = errors.New("Already logged out") |
13 | 16 |
|
| 17 | +// ErrAlreadyCompress is returned by Client.Compress when compression has |
| 18 | +// already been enabled on the client. |
| 19 | +var ErrAlreadyCompressed = errors.New("COMPRESS is already enabled") |
| 20 | + |
14 | 21 | // Capability requests a listing of capabilities that the server supports. |
15 | 22 | // Capabilities are often returned by the server with the greeting or with the |
16 | 23 | // STARTTLS and LOGIN responses, so usually explicitly requesting capabilities |
@@ -86,3 +93,35 @@ func (c *Client) Logout() error { |
86 | 93 | } |
87 | 94 | return nil |
88 | 95 | } |
| 96 | + |
| 97 | +// Compress instructs the server to use the named compression mechanism for all |
| 98 | +// commands and/or responses. |
| 99 | +func (c *Client) Compress(mech string) error { |
| 100 | + if c.isCompressed { |
| 101 | + return ErrAlreadyCompressed |
| 102 | + } |
| 103 | + |
| 104 | + if ok, err := c.Support("COMPRESS=" + mech); !ok || err != nil { |
| 105 | + return imap.CompressUnsupportedError{Mechanism: mech} |
| 106 | + } |
| 107 | + if mech != imap.CompressDeflate { |
| 108 | + return imap.CompressUnsupportedError{Mechanism: mech} |
| 109 | + } |
| 110 | + |
| 111 | + cmd := &commands.Compress{Mechanism: mech} |
| 112 | + err := c.Upgrade(func(conn net.Conn) (net.Conn, error) { |
| 113 | + if status, err := c.Execute(cmd, nil); err != nil { |
| 114 | + return nil, err |
| 115 | + } else if err := status.Err(); err != nil { |
| 116 | + return nil, err |
| 117 | + } |
| 118 | + |
| 119 | + return internal.CreateDeflateConn(conn, flate.DefaultCompression) |
| 120 | + }) |
| 121 | + if err != nil { |
| 122 | + return err |
| 123 | + } |
| 124 | + |
| 125 | + c.isCompressed = true |
| 126 | + return nil |
| 127 | +} |
0 commit comments