@@ -25,6 +25,7 @@ type message struct {
25
25
RcptOpts []* smtp.RcptOptions
26
26
Data []byte
27
27
Opts * smtp.MailOptions
28
+ XForward map [string ]string
28
29
}
29
30
30
31
type backend struct {
@@ -98,7 +99,9 @@ func (s *session) Auth(mech string) (sasl.Server, error) {
98
99
}
99
100
100
101
func (s * session ) Reset () {
101
- s .msg = & message {}
102
+ s .msg = & message {
103
+ XForward : make (map [string ]string ),
104
+ }
102
105
}
103
106
104
107
func (s * session ) Logout () error {
@@ -157,6 +160,11 @@ func (s *session) Data(r io.Reader) error {
157
160
return nil
158
161
}
159
162
163
+ func (s * session ) XForward (attrName , attrValue string ) error {
164
+ s .msg .XForward [attrName ] = attrValue
165
+ return nil
166
+ }
167
+
160
168
func (s * session ) LMTPData (r io.Reader , collector smtp.StatusCollector ) error {
161
169
if err := s .Data (r ); err != nil {
162
170
return err
@@ -1712,3 +1720,90 @@ func TestServerMTPRIORITY(t *testing.T) {
1712
1720
t .Fatal ("Incorrect MtPriority parameter value:" , fmt .Sprintf ("expected %d, got %d" , expectedPriority , * priority ))
1713
1721
}
1714
1722
}
1723
+
1724
+ func TestServerXFORWARD (t * testing.T ) {
1725
+ be , s , c , scanner , caps := testServerEhlo (t ,
1726
+ func (s * smtp.Server ) {
1727
+ s .EnableXFORWARD = true
1728
+ })
1729
+ defer s .Close ()
1730
+ defer c .Close ()
1731
+
1732
+ if _ , ok := caps ["XFORWARD NAME ADDR PROTO HELO" ]; ! ok {
1733
+ t .Fatal ("Missing capability: XFORWARD" )
1734
+ }
1735
+
1736
+ io .
WriteString (
c ,
"MAIL FROM:<[email protected] >\r \n " )
1737
+ scanner .Scan ()
1738
+ if ! strings .HasPrefix (scanner .Text (), "250 " ) {
1739
+ t .Fatal ("Invalid MAIL response:" , scanner .Text ())
1740
+ }
1741
+
1742
+ io .
WriteString (
c ,
"RCPT TO:<[email protected] >\r \n " )
1743
+ scanner .Scan ()
1744
+ if ! strings .HasPrefix (scanner .Text (), "250 " ) {
1745
+ t .Fatal ("Invalid RCPT response:" , scanner .Text ())
1746
+ }
1747
+
1748
+ // Atrribute names are case insensitive, check we normalised them
1749
+ io .WriteString (c , "XFORWARD NAME=spike.porcupine.org ADDR=168.100.189.2 proto=ESMTP\r \n " )
1750
+ scanner .Scan ()
1751
+ if ! strings .HasPrefix (scanner .Text (), "250 " ) {
1752
+ t .Fatal ("Invalid XFORWARD response:" , scanner .Text ())
1753
+ }
1754
+
1755
+ io .WriteString (c , "DATA\r \n " )
1756
+ scanner .Scan ()
1757
+ if ! strings .HasPrefix (scanner .Text (), "354 " ) {
1758
+ t .Fatal ("Invalid DATA response:" , scanner .Text ())
1759
+ }
1760
+
1761
+ io .
WriteString (
c ,
"From: [email protected] \r \n " )
1762
+ io .WriteString (c , "\r \n " )
1763
+ io .WriteString (c , "Hey\r <3\r \n " )
1764
+ io .WriteString (c , "..this dot is fine\r \n " )
1765
+ io .WriteString (c , ".\r \n " )
1766
+ scanner .Scan ()
1767
+ if ! strings .HasPrefix (scanner .Text (), "250 " ) {
1768
+ t .Fatal ("Invalid DATA response:" , scanner .Text ())
1769
+ }
1770
+
1771
+ if len (be .messages ) != 0 || len (be .anonmsgs ) != 1 {
1772
+ t .Fatal ("Invalid number of sent messages:" , be .messages , be .anonmsgs )
1773
+ }
1774
+
1775
+ msg := be .anonmsgs [0 ]
1776
+
1777
+ if len (msg .XForward ) != 3 {
1778
+ t .Fatal ("Invalid XFORWARD data:" , msg .XForward )
1779
+ }
1780
+
1781
+ if got , ok := msg .XForward ["NAME" ]; ! ok {
1782
+ t .Fatal ("Missing XFORWARD attribute NAME" )
1783
+ } else if got != "spike.porcupine.org" {
1784
+ t .Fatal ("Invalid XFORWARD attribute value for NAME" , got )
1785
+ }
1786
+
1787
+ if got , ok := msg .XForward ["ADDR" ]; ! ok {
1788
+ t .Fatal ("Missing XFORWARD attribute ADDR" )
1789
+ } else if got != "168.100.189.2" {
1790
+ t .Fatal ("Invalid XFORWARD attribute value for ADDR" , got )
1791
+ }
1792
+
1793
+ if got , ok := msg .XForward ["PROTO" ]; ! ok {
1794
+ t .Fatal ("Missing (normalised) XFORWARD attribute PROTO" )
1795
+ } else if got != "ESMTP" {
1796
+ t .Fatal ("Invalid (normalised) XFORWARD attribute value for PROTO" , got )
1797
+ }
1798
+
1799
+ // Sanity that the rest of the connection continued fine
1800
+ if msg .
From != "[email protected] " {
1801
+ t .Fatal ("Invalid mail sender:" , msg .From )
1802
+ }
1803
+ if len (
msg .
To )
!= 1 || msg .
To [
0 ]
!= "[email protected] " {
1804
+ t .Fatal ("Invalid mail recipients:" , msg .To )
1805
+ }
1806
+ if string (
msg .
Data )
!= "From: [email protected] \r \n \r \n Hey\r <3\r \n .this dot is fine\r \n " {
1807
+ t .Fatal ("Invalid mail data:" , string (msg .Data ))
1808
+ }
1809
+ }
0 commit comments