| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 | 
							- package backends
 
- import (
 
- 	"bytes"
 
- 	"compress/zlib"
 
- 	"github.com/flashmob/go-guerrilla/mail"
 
- 	"io"
 
- 	"sync"
 
- )
 
- // ----------------------------------------------------------------------------------
 
- // Processor Name: compressor
 
- // ----------------------------------------------------------------------------------
 
- // Description   : Compress the e.Data (email data) and e.DeliveryHeader together
 
- // ----------------------------------------------------------------------------------
 
- // Config Options: None
 
- // --------------:-------------------------------------------------------------------
 
- // Input         : e.Data, e.DeliveryHeader generated by Header() processor
 
- // ----------------------------------------------------------------------------------
 
- // Output        : sets the pointer to a compressor in e.Info["zlib-compressor"]
 
- //               : to write the compressed data, simply use fmt to print as a string,
 
- //               : eg. fmt.Println("%s", e.Info["zlib-compressor"])
 
- //               : or just call the String() func .Info["zlib-compressor"].String()
 
- //               : Note that it can only be outputted once. It destroys the buffer
 
- //               : after being printed
 
- // ----------------------------------------------------------------------------------
 
- func init() {
 
- 	processors["compressor"] = func() Decorator {
 
- 		return Compressor()
 
- 	}
 
- }
 
- // compressedData struct will be compressed using zlib when printed via fmt
 
- type DataCompressor struct {
 
- 	extraHeaders []byte
 
- 	data         *bytes.Buffer
 
- 	// the pool is used to recycle buffers to ease up on the garbage collector
 
- 	pool *sync.Pool
 
- }
 
- // newCompressedData returns a new CompressedData
 
- func newCompressor() *DataCompressor {
 
- 	// grab it from the pool
 
- 	var p = sync.Pool{
 
- 		// if not available, then create a new one
 
- 		New: func() interface{} {
 
- 			var b bytes.Buffer
 
- 			return &b
 
- 		},
 
- 	}
 
- 	return &DataCompressor{
 
- 		pool: &p,
 
- 	}
 
- }
 
- // Set the extraheaders and buffer of data to compress
 
- func (c *DataCompressor) set(b []byte, d *bytes.Buffer) {
 
- 	c.extraHeaders = b
 
- 	c.data = d
 
- }
 
- // String implements the Stringer interface.
 
- // Can only be called once!
 
- // This is because the compression buffer will be reset and compressor will be returned to the pool
 
- func (c *DataCompressor) String() string {
 
- 	if c.data == nil {
 
- 		return ""
 
- 	}
 
- 	//borrow a buffer form the pool
 
- 	b := c.pool.Get().(*bytes.Buffer)
 
- 	// put back in the pool
 
- 	defer func() {
 
- 		b.Reset()
 
- 		c.pool.Put(b)
 
- 	}()
 
- 	var r *bytes.Reader
 
- 	w, _ := zlib.NewWriterLevel(b, zlib.BestSpeed)
 
- 	r = bytes.NewReader(c.extraHeaders)
 
- 	_, _ = io.Copy(w, r)
 
- 	_, _ = io.Copy(w, c.data)
 
- 	_ = w.Close()
 
- 	return b.String()
 
- }
 
- // clear it, without clearing the pool
 
- func (c *DataCompressor) clear() {
 
- 	c.extraHeaders = []byte{}
 
- 	c.data = nil
 
- }
 
- func Compressor() Decorator {
 
- 	return func(p Processor) Processor {
 
- 		return ProcessWith(func(e *mail.Envelope, task SelectTask) (Result, error) {
 
- 			if task == TaskSaveMail {
 
- 				compressor := newCompressor()
 
- 				compressor.set([]byte(e.DeliveryHeader), &e.Data)
 
- 				// put the pointer in there for other processors to use later in the line
 
- 				e.Values["zlib-compressor"] = compressor
 
- 				// continue to the next Processor in the decorator stack
 
- 				return p.Process(e, task)
 
- 			} else {
 
- 				return p.Process(e, task)
 
- 			}
 
- 		})
 
- 	}
 
- }
 
 
  |