Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120837949
rcube_smtp.inc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
rcube_smtp.inc
View Options
<
?
php
/*
+-----------------------------------------------------------------------+
| program/include/rcube_smtp.inc |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2005-2007, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Provide SMTP functionality using socket connections |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id$
*/
/**
* SMTP delivery functions
*
* @package Mail
*/
// define headers delimiter
define
(
'
SMTP_MIME_CRLF
'
,
"\r\n"
);
$
SMTP_CONN
=
null
;
/**
* Function for sending mail using SMTP.
*
* @param string Sender e-Mail address
*
* @param mixed Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param mixed The message headers to send with the mail
* Either as an associative array or a finally
* formatted string
*
* @param string The full text of the message body, including any Mime parts, etc.
*
* @return bool Returns TRUE on success, or FALSE on error
*/
function
smtp_mail
(
$
from
,
$
recipients
,
&$
headers
,
&$
body
,
&$
response
,
&$
error
)
{
global
$
SMTP_CONN
,
$
RCMAIL
;
// let plugins alter smtp connection config
$
CONFIG
=
$
RCMAIL
-
>
plugins
-
>
exec_hook
(
'
smtp_connect
'
,
array
(
'
smtp_server
'
=
>
$
RCMAIL
-
>
config
-
>
get
(
'
smtp_server
'
),
'
smtp_port
'
=
>
$
RCMAIL
-
>
config
-
>
get
(
'
smtp_port
'
,
25
),
'
smtp_user
'
=
>
$
RCMAIL
-
>
config
-
>
get
(
'
smtp_user
'
),
'
smtp_pass
'
=
>
$
RCMAIL
-
>
config
-
>
get
(
'
smtp_pass
'
),
'
smtp_auth_type
'
=
>
$
RCMAIL
-
>
config
-
>
get
(
'
smtp_auth_type
'
),
'
smtp_helo_host
'
=
>
$
RCMAIL
-
>
config
-
>
get
(
'
smtp_helo_host
'
),
));
$
smtp_timeout
=
null
;
$
smtp_host
=
str_replace
(
'%
h
'
,
$
_SESSION
[
'
imap_host
'
],
$
CONFIG
[
'
smtp_server
'
]);
$
smtp_port
=
is_numeric
(
$
CONFIG
[
'
smtp_port
'
])
?
$
CONFIG
[
'
smtp_port
'
]
:
25
;
$
smtp_host_url
=
parse_url
(
$
smtp_host
);
// overwrite port
if
(
isset
(
$
smtp_host_url
[
'
host
'
])
&&
isset
(
$
smtp_host_url
[
'
port
'
]))
{
$
smtp_host
=
$
smtp_host_url
[
'
host
'
];
$
smtp_port
=
$
smtp_host_url
[
'
port
'
];
}
// re-write smtp host
if
(
isset
(
$
smtp_host_url
[
'
host
'
])
&&
isset
(
$
smtp_host_url
[
'
scheme
'
]))
$
smtp_host
=
sprintf
(
'%
s
:
//%s', $smtp_host_url['scheme'], $smtp_host_url['host']);
// create Net_SMTP object and connect to server
if
(
!
is_object
(
$
SMTP_CONN
))
{
if
(
!
empty
(
$
CONFIG
[
'
smtp_helo_host
'
]))
$
helo_host
=
$
CONFIG
[
'
smtp_helo_host
'
];
else
if
(
!
empty
(
$
_SERVER
[
'
SERVER_NAME
'
]))
$
helo_host
=
preg_replace
(
'
/
:\
d
+
$
/
'
,
''
,
$
_SERVER
[
'
SERVER_NAME
'
]);
else
$
helo_host
=
'
localhost
'
;
$
SMTP_CONN
=
new
Net_SMTP
(
$
smtp_host
,
$
smtp_port
,
$
helo_host
);
if
(
$
RCMAIL
-
>
config
-
>
get
(
'
smtp_debug
'
))
$
SMTP_CONN
-
>
setDebug
(
true
,
'
smtp_debug_handler
'
);
// try to connect to server and exit on failure
$
result
=
$
SMTP_CONN
-
>
connect
(
$
smtp_timeout
);
if
(
PEAR
::
isError
(
$
result
))
{
$
response
[]
=
"Connection failed: "
.$
result
-
>
getMessage
();
$
error
=
array
(
'
label
'
=
>
'
smtpconnerror
'
,
'
vars
'
=
>
array
(
'
code
'
=
>
$
SMTP_CONN
-
>
_code
));
$
SMTP_CONN
=
null
;
return
FALSE
;
}
// attempt to authenticate to the SMTP server
if
(
$
CONFIG
[
'
smtp_user
'
]
&&
$
CONFIG
[
'
smtp_pass
'
])
{
if
(
strstr
(
$
CONFIG
[
'
smtp_user
'
],
'%
u
'
))
$
smtp_user
=
str_replace
(
'%
u
'
,
$
_SESSION
[
'
username
'
],
$
CONFIG
[
'
smtp_user
'
]);
else
$
smtp_user
=
$
CONFIG
[
'
smtp_user
'
];
if
(
strstr
(
$
CONFIG
[
'
smtp_pass
'
],
'%
p
'
))
$
smtp_pass
=
str_replace
(
'%
p
'
,
$
RCMAIL
-
>
decrypt
(
$
_SESSION
[
'
password
'
]),
$
CONFIG
[
'
smtp_pass
'
]);
else
$
smtp_pass
=
$
CONFIG
[
'
smtp_pass
'
];
$
smtp_auth_type
=
empty
(
$
CONFIG
[
'
smtp_auth_type
'
])
?
NULL
:
$
CONFIG
[
'
smtp_auth_type
'
];
$
result
=
$
SMTP_CONN
-
>
auth
(
$
smtp_user
,
$
smtp_pass
,
$
smtp_auth_type
);
if
(
PEAR
::
isError
(
$
result
))
{
$
error
=
array
(
'
label
'
=
>
'
smtpautherror
'
,
'
vars
'
=
>
array
(
'
code
'
=
>
$
SMTP_CONN
-
>
_code
));
$
response
[]
.
=
'
Authentication
failure
:
'
.
$
result
-
>
getMessage
()
.
'
(
Code
:
'
.
$
result
-
>
getCode
()
.
'
)
'
;
smtp_reset
();
return
FALSE
;
}
}
}
// prepare message headers as string
if
(
is_array
(
$
headers
))
{
$
headerElements
=
smtp_prepare_headers
(
$
headers
);
if
(
!$
headerElements
)
{
smtp_reset
();
return
FALSE
;
}
list
(
$
from
,
$
text_headers
)
=
$
headerElements
;
}
else
if
(
is_string
(
$
headers
))
$
text_headers
=
$
headers
;
else
{
smtp_reset
();
$
response
[]
.
=
"Invalid message headers"
;
return
FALSE
;
}
// exit if no from address is given
if
(
!
isset
(
$
from
))
{
smtp_reset
();
$
response
[]
.
=
"No From address has been provided"
;
return
FALSE
;
}
// set From: address
if
(
PEAR
::
isError
(
$
SMTP_CONN
-
>
mailFrom
(
$
from
)))
{
$
error
=
array
(
'
label
'
=
>
'
smtpfromerror
'
,
'
vars
'
=
>
array
(
'
from
'
=
>
$
from
,
'
code
'
=
>
$
SMTP_CONN
-
>
_code
));
$
response
[]
.
=
"Failed to set sender '$from'"
;
smtp_reset
();
return
FALSE
;
}
// prepare list of recipients
$
recipients
=
smtp_parse_rfc822
(
$
recipients
);
if
(
PEAR
::
isError
(
$
recipients
))
{
$
error
=
array
(
'
label
'
=
>
'
smtprecipientserror
'
);
smtp_reset
();
return
FALSE
;
}
// set mail recipients
foreach
(
$
recipients
as
$
recipient
)
{
if
(
PEAR
::
isError
(
$
SMTP_CONN
-
>
rcptTo
(
$
recipient
)))
{
$
error
=
array
(
'
label
'
=
>
'
smtptoerror
'
,
'
vars
'
=
>
array
(
'
to
'
=
>
$
recipient
,
'
code
'
=
>
$
SMTP_CONN
-
>
_code
));
$
response
[]
.
=
"Failed to add recipient '$recipient'"
;
smtp_reset
();
return
FALSE
;
}
}
// Concatenate headers and body so it can be passed by reference to SMTP_CONN->data
// so preg_replace in SMTP_CONN->quotedata will store a reference instead of a copy.
// We are still forced to make another copy here for a couple ticks so we don't really
// get to save a copy in the method call.
$
data
=
$
text_headers
.
"\r\n"
.
$
body
;
// unset old vars to save data and so we can pass into SMTP_CONN->data by reference.
unset
(
$
text_headers
,
$
body
);
// Send the message's headers and the body as SMTP data.
if
(
PEAR
::
isError
(
$
result
=
$
SMTP_CONN
-
>
data
(
$
data
)))
{
$
error
=
array
(
'
label
'
=
>
'
smtperror
'
,
'
vars
'
=
>
array
(
'
msg
'
=
>
$
result
-
>
getMessage
()));
$
response
[]
.
=
"Failed to send data"
;
smtp_reset
();
return
FALSE
;
}
$
response
[]
=
join
(
':
'
,
$
SMTP_CONN
-
>
getResponse
());
return
TRUE
;
}
/**
* Reset the global SMTP connection
* @access public
*/
function
smtp_reset
()
{
global
$
SMTP_CONN
;
if
(
is_object
(
$
SMTP_CONN
)
&&
is_resource
(
$
SMTP_CONN
-
>
_socket
-
>
fp
))
{
$
SMTP_CONN
-
>
rset
();
smtp_disconnect
();
}
}
/**
* Disconnect the global SMTP connection and destroy object
* @access public
*/
function
smtp_disconnect
()
{
global
$
SMTP_CONN
;
if
(
is_object
(
$
SMTP_CONN
))
{
$
SMTP_CONN
-
>
disconnect
();
$
SMTP_CONN
=
null
;
}
}
/* this is our own debug handler for the SMTP connection */
function
smtp_debug_handler
(
&$
smtp
,
$
message
)
{
write_log
(
'
smtp
'
,
preg_replace
(
'
/
\
r
\
n
$
/
'
,
''
,
$
message
));
}
/**
* Take an array of mail headers and return a string containing
* text usable in sending a message.
*
* @param array $headers The array of headers to prepare, in an associative
* array, where the array key is the header name (ie,
* 'Subject'), and the array value is the header
* value (ie, 'test'). The header produced from those
* values would be 'Subject: test'.
*
* @return mixed Returns false if it encounters a bad address,
* otherwise returns an array containing two
* elements: Any From: address found in the headers,
* and the plain text version of the headers.
* @access private
*/
function
smtp_prepare_headers
(
$
headers
)
{
$
lines
=
array
();
$
from
=
null
;
foreach
(
$
headers
as
$
key
=
>
$
value
)
{
if
(
strcasecmp
(
$
key
,
'
From
'
)
===
0
)
{
$
addresses
=
smtp_parse_rfc822
(
$
value
);
if
(
is_array
(
$
addresses
))
$
from
=
$
addresses
[
0
];
// Reject envelope From: addresses with spaces.
if
(
strstr
(
$
from
,
'
'
))
return
FALSE
;
$
lines
[]
=
$
key
.
':
'
.
$
value
;
}
else
if
(
strcasecmp
(
$
key
,
'
Received
'
)
===
0
)
{
$
received
=
array
();
if
(
is_array
(
$
value
))
{
foreach
(
$
value
as
$
line
)
$
received
[]
=
$
key
.
':
'
.
$
line
;
}
else
{
$
received
[]
=
$
key
.
':
'
.
$
value
;
}
// Put Received: headers at the top. Spam detectors often
// flag messages with Received: headers after the Subject:
// as spam.
$
lines
=
array_merge
(
$
received
,
$
lines
);
}
else
{
// If $value is an array (i.e., a list of addresses), convert
// it to a comma-delimited string of its elements (addresses).
if
(
is_array
(
$
value
))
$
value
=
implode
(
'
,
'
,
$
value
);
$
lines
[]
=
$
key
.
':
'
.
$
value
;
}
}
return
array
(
$
from
,
join
(
SMTP_MIME_CRLF
,
$
lines
)
.
SMTP_MIME_CRLF
);
}
/**
* Take a set of recipients and parse them, returning an array of
* bare addresses (forward paths) that can be passed to sendmail
* or an smtp server with the rcpt to: command.
*
* @param mixed Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid.
*
* @return array An array of forward paths (bare addresses).
* @access private
*/
function
smtp_parse_rfc822
(
$
recipients
)
{
// if we're passed an array, assume addresses are valid and implode them before parsing.
if
(
is_array
(
$
recipients
))
$
recipients
=
implode
(
'
,
'
,
$
recipients
);
$
addresses
=
array
();
$
recipients
=
rcube_explode_quoted_string
(
'
,
'
,
$
recipients
);
reset
(
$
recipients
);
while
(
list
(
$
k
,
$
recipient
)
=
each
(
$
recipients
))
{
$
a
=
explode
(
" "
,
$
recipient
);
while
(
list
(
$
k2
,
$
word
)
=
each
(
$
a
))
{
if
((
strpos
(
$
word
,
"@"
)
>
0
)
&&
(
strpos
(
$
word
,
"\""
)
===
false
))
{
$
word
=
preg_replace
(
'
/
^
<
|
>
$
/
'
,
''
,
trim
(
$
word
));
if
(
in_array
(
$
word
,
$
addresses
)
===
false
)
array_push
(
$
addresses
,
$
word
);
}
}
}
return
$
addresses
;
}
?
>
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, Apr 24, 1:52 PM (5 d, 23 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18846830
Default Alt Text
rcube_smtp.inc (10 KB)
Attached To
Mode
R113 roundcubemail
Attached
Detach File
Event Timeline