Overview

Namespaces

  • Composer
    • Autoload
  • Geekwright
    • RegDom
  • League
    • OAuth2
      • Client
        • Provider
  • None
  • Xmf
    • Database
    • Jwt
    • Key
    • Module
      • Helper

Classes

  • ArtObject
  • ArtObjectHandler
  • BloggerApi
  • CGIF
  • CGIFCOLORTABLE
  • CGIFFILEHEADER
  • CGIFIMAGE
  • CGIFIMAGEHEADER
  • CGIFLZW
  • Composer\Autoload\ClassLoader
  • Composer\Autoload\ComposerStaticInit274e5fff219a4f27a346e611b0580d6a
  • ComposerAutoloaderInit274e5fff219a4f27a346e611b0580d6a
  • Config_File
  • Cookie
  • Criteria
  • CriteriaCompo
  • CriteriaElement
  • Database
  • Db_manager
  • ErrorHandler
  • FormDhtmlTextArea
  • FormTextArea
  • Geekwright\RegDom\PublicSuffixList
  • Geekwright\RegDom\RegisteredDomain
  • HTMLPurifier
  • League\OAuth2\Client\Provider\Google
  • MetaWeblogApi
  • ModuleAdmin
  • MovableTypeApi
  • MyTextSanitizer
  • MyTextSanitizerExtended
  • MyTextSanitizerExtension
  • MytsCensor
  • MytsFlash
  • MytsIframe
  • MytsImage
  • MytsLi
  • MytsMms
  • MytsMp3
  • MytsRtsp
  • MytsSoundcloud
  • MytsSyntaxhighlight
  • MytsTextfilter
  • MytsUl
  • MytsWiki
  • MytsWmp
  • MytsYoutube
  • PathStuffController
  • PHPMailer
  • PHPMailerOAuth
  • PHPMailerOAuthGoogle
  • phpthumb
  • phpthumb_bmp
  • phpthumb_filters
  • phpthumb_functions
  • phpthumb_ico
  • phpUnsharpMask
  • PmCorePreload
  • PmMessage
  • PmMessageHandler
  • PmSystemPreload
  • POP3
  • ProfileCategory
  • ProfileCategoryHandler
  • ProfileCorePreload
  • ProfileField
  • ProfileFieldHandler
  • ProfileProfile
  • ProfileProfileHandler
  • ProfileRegstep
  • ProfileRegstepHandler
  • ProfileVisibility
  • ProfileVisibilityHandler
  • Protector
  • Protector_bruteforce_overrun_message
  • Protector_crawler_overrun_message
  • Protector_f5attack_overrun_message
  • Protector_postcommon_post_deny_by_httpbl
  • Protector_postcommon_post_deny_by_rbl
  • Protector_postcommon_post_htmlpurify4everyone
  • Protector_postcommon_post_htmlpurify4guest
  • Protector_postcommon_post_language_match
  • Protector_postcommon_post_need_multibyte
  • Protector_postcommon_post_register_moratorium
  • Protector_postcommon_post_stopforumspam
  • Protector_postcommon_register_insert_js_check
  • Protector_postcommon_register_stopforumspam
  • Protector_precommon_badip_errorlog
  • Protector_precommon_badip_message
  • Protector_precommon_badip_redirection
  • Protector_precommon_bwlimit_errorlog
  • Protector_precommon_bwlimit_message
  • Protector_prepurge_exit_message
  • Protector_spamcheck_overrun_message
  • ProtectorCorePreload
  • ProtectorFilterAbstract
  • ProtectorFilterHandler
  • ProtectorMySQLDatabase
  • ProtectorRegistry
  • ReCaptchaResponse
  • RpcArrayHandler
  • RpcBase64Handler
  • RpcBooleanHandler
  • RpcDateTimeHandler
  • RpcDoubleHandler
  • RpcIntHandler
  • RpcMemberHandler
  • RpcMethodNameHandler
  • RpcNameHandler
  • RpcStringHandler
  • RpcStructHandler
  • RpcValueHandler
  • RssAuthorHandler
  • RssCategoryHandler
  • RssChannelHandler
  • RssCommentsHandler
  • RssCopyrightHandler
  • RssDescriptionHandler
  • RssDocsHandler
  • RssGeneratorHandler
  • RssGuidHandler
  • RssHeightHandler
  • RssImageHandler
  • RssItemHandler
  • RssLanguageHandler
  • RssLastBuildDateHandler
  • RssLinkHandler
  • RssManagingEditorHandler
  • RssNameHandler
  • RssPubDateHandler
  • RssSourceHandler
  • RssTextInputHandler
  • RssTitleHandler
  • RssTtlHandler
  • RssUrlHandler
  • RssWebMasterHandler
  • RssWidthHandler
  • SaxParser
  • Smarty
  • Smarty_Compiler
  • SMTP
  • Snoopy
  • SqlUtility
  • SystemAvatar
  • SystemAvatarHandler
  • SystemBanner
  • SystemBannerclient
  • SystemBannerclientHandler
  • SystemBannerFinish
  • SystemBannerfinishHandler
  • SystemBannerHandler
  • SystemBlock
  • SystemBlockHandler
  • SystemBlockLinkModule
  • SystemBlockLinkModuleHandler
  • SystemBreadcrumb
  • SystemCorePreload
  • SystemFineAvatarUploadHandler
  • SystemFineImUploadHandler
  • SystemFineUploadHandler
  • SystemGroup
  • SystemGroupHandler
  • SystemMaintenance
  • SystemMenuHandler
  • SystemSmilies
  • SystemsmiliesHandler
  • SystemUserrank
  • SystemuserrankHandler
  • SystemUsers
  • SystemUsersHandler
  • Tar
  • ThemeSetAuthorHandler
  • ThemeSetDateCreatedHandler
  • ThemeSetDescriptionHandler
  • ThemeSetEmailHandler
  • ThemeSetFileTypeHandler
  • ThemeSetGeneratorHandler
  • ThemeSetImageHandler
  • ThemeSetLinkHandler
  • ThemeSetModuleHandler
  • ThemeSetNameHandler
  • ThemeSetTagHandler
  • ThemeSetTemplateHandler
  • TinyMCE
  • Xmf\Assert
  • Xmf\Database\Migrate
  • Xmf\Database\TableLoad
  • Xmf\Database\Tables
  • Xmf\Debug
  • Xmf\FilterInput
  • Xmf\Highlighter
  • Xmf\IPAddress
  • Xmf\Jwt\JsonWebToken
  • Xmf\Jwt\KeyFactory
  • Xmf\Jwt\TokenFactory
  • Xmf\Jwt\TokenReader
  • Xmf\Key\ArrayStorage
  • Xmf\Key\Basic
  • Xmf\Key\FileStorage
  • Xmf\Key\KeyAbstract
  • Xmf\Language
  • Xmf\Metagen
  • Xmf\Module\Admin
  • Xmf\Module\Helper
  • Xmf\Module\Helper\AbstractHelper
  • Xmf\Module\Helper\Cache
  • Xmf\Module\Helper\GenericHelper
  • Xmf\Module\Helper\Permission
  • Xmf\Module\Helper\Session
  • Xmf\Random
  • Xmf\Request
  • Xmf\StopWords
  • Xmf\Yaml
  • XmlTagHandler
  • XoopsApi
  • xoopsart
  • XoopsAuth
  • XoopsAuthAds
  • XoopsAuthFactory
  • XoopsAuthLdap
  • XoopsAuthProvisionning
  • XoopsAuthXoops
  • XoopsAvatar
  • XoopsAvatarHandler
  • XoopsBlock
  • XoopsBlockHandler
  • XoopsBlockInstance
  • XoopsBlockInstanceHandler
  • XoopsCache
  • XoopsCacheApc
  • XoopsCacheEngine
  • XoopsCacheFile
  • XoopsCacheMemcache
  • XoopsCacheModel
  • XoopsCacheModelHandler
  • XoopsCacheModelObject
  • XoopsCacheXcache
  • XoopsCaptcha
  • XoopsCaptchaImage
  • XoopsCaptchaImageHandler
  • XoopsCaptchaMethod
  • XoopsCaptchaRecaptcha
  • XoopsCaptchaRecaptcha2
  • XoopsCaptchaText
  • XoopsComment
  • XoopsCommentHandler
  • XoopsCommentRenderer
  • XoopsComments
  • XoopsConfigCategory
  • XoopsConfigCategoryHandler
  • XoopsConfigHandler
  • XoopsConfigItem
  • XoopsConfigItemHandler
  • XoopsConfigOption
  • XoopsConfigOptionHandler
  • XoopsDatabase
  • XoopsDatabaseFactory
  • XoopsDownloader
  • XoopsEditor
  • XoopsEditorHandler
  • XoopsErrorHandler
  • XoopsFile
  • XoopsFileHandler
  • XoopsFilterInput
  • XoopsFolderHandler
  • XoopsForm
  • XoopsFormButton
  • XoopsFormButtonTray
  • XoopsFormCaptcha
  • XoopsFormCheckBox
  • XoopsFormColorPicker
  • XoopsFormDateTime
  • XoopsFormDhtmlTextArea
  • XoopsFormEditor
  • XoopsFormElement
  • XoopsFormElementTray
  • XoopsFormFile
  • XoopsFormHidden
  • XoopsFormHiddenToken
  • XoopsFormLabel
  • XoopsFormPassword
  • XoopsFormRadio
  • XoopsFormRadioYN
  • XoopsFormRenderer
  • XoopsFormRendererBootstrap3
  • XoopsFormRendererLegacy
  • XoopsFormSelect
  • XoopsFormSelectCheckGroup
  • XoopsFormSelectCountry
  • XoopsFormSelectEditor
  • XoopsFormSelectGroup
  • XoopsFormSelectLang
  • XoopsFormSelectMatchOption
  • XoopsFormSelectTheme
  • XoopsFormSelectTimezone
  • XoopsFormSelectUser
  • XoopsFormText
  • XoopsFormTextArea
  • XoopsFormTextDateSelect
  • XoopsFormTinymce
  • XoopsGroup
  • XoopsGroupFormCheckBox
  • XoopsGroupHandler
  • XoopsGroupPerm
  • XoopsGroupPermForm
  • XoopsGroupPermHandler
  • XoopsGTicket
  • XoopsGuestUser
  • XoopsGuiDefault
  • XoopsGuiThadmin
  • XoopsGuiTransition
  • XoopsGuiZetadigme
  • XoopsHandlerRegistry
  • XoopsImage
  • XoopsImagecategory
  • XoopsImagecategoryHandler
  • XoopsImageHandler
  • XoopsImageSet
  • XoopsImagesetHandler
  • XoopsImagesetimg
  • XoopsImagesetimgHandler
  • XoopsInstallWizard
  • XoopsLists
  • XoopsLoad
  • XoopsLocal
  • XoopsLocalAbstract
  • XoopsLocalWrapper
  • XoopsLogger
  • XoopsMailer
  • XoopsMailerLocal
  • XoopsMediaUploader
  • XoopsMemberHandler
  • XoopsMembership
  • XoopsMembershipHandler
  • XoopsModelAbstract
  • XoopsModelFactory
  • XoopsModelJoint
  • XoopsModelRead
  • XoopsModelStats
  • XoopsModelSync
  • XoopsModelWrite
  • XoopsModule
  • XoopsModuleHandler
  • XoopsMultiMailer
  • XoopsMySQLDatabase
  • XoopsMySQLDatabaseProxy
  • XoopsMySQLDatabaseSafe
  • XoopsNotification
  • XoopsNotificationHandler
  • XoopsObject
  • XoopsObjectHandler
  • XoopsObjectTree
  • XoopsOnlineHandler
  • XoopsPageNav
  • XoopsPersistableObjectHandler
  • XoopsPreload
  • XoopsPreloadItem
  • XoopsPrivmessage
  • XoopsPrivmessageHandler
  • XoopsRank
  • XoopsRankHandler
  • XoopsRequest
  • XoopsSecurity
  • XoopsSessionHandler
  • XoopsSimpleForm
  • XoopsStory
  • XoopsSystemCpanel
  • XoopsSystemGui
  • XoopsTableForm
  • XoopsTarDownloader
  • XoopsThemeForm
  • XoopsThemeSetParser
  • XoopsTopic
  • XoopsTpl
  • XoopsTplfile
  • XoopsTplfileHandler
  • XoopsTplset
  • XoopsTplsetHandler
  • XoopsTree
  • XoopsUser
  • XoopsUserHandler
  • XoopsUserUtility
  • XoopsUtility
  • XoopsXmlRpcApi
  • XoopsXmlRpcArray
  • XoopsXmlRpcBase64
  • XoopsXmlRpcBoolean
  • XoopsXmlRpcDatetime
  • XoopsXmlRpcDocument
  • XoopsXmlRpcDouble
  • XoopsXmlRpcFault
  • XoopsXmlRpcInt
  • XoopsXmlRpcParser
  • XoopsXmlRpcRequest
  • XoopsXmlRpcResponse
  • XoopsXmlRpcString
  • XoopsXmlRpcStruct
  • XoopsXmlRpcTag
  • XoopsXmlRss2Parser
  • XoopsZipDownloader
  • xos_kernel_Xoops2
  • xos_logos_PageBuilder
  • xos_opal_AdminThemeFactory
  • xos_opal_Theme
  • xos_opal_ThemeFactory
  • XoUser
  • XoUserHandler
  • Zipfile

Interfaces

  • Xmf\Key\StorageInterface
  • XoopsFormRendererInterface

Exceptions

  • phpmailerException

Functions

  • __autoload
  • _recaptcha_aes_encrypt
  • _recaptcha_aes_pad
  • _recaptcha_http_post
  • _recaptcha_mailhide_email_parts
  • _recaptcha_mailhide_urlbase64
  • _recaptcha_qsencode
  • _smarty_regex_replace_check
  • _smarty_sort_length
  • admin_refcheck
  • b_system_comments_edit
  • b_system_comments_show
  • b_system_info_edit
  • b_system_info_show
  • b_system_login_show
  • b_system_main_show
  • b_system_newmembers_edit
  • b_system_newmembers_show
  • b_system_notification_show
  • b_system_online_show
  • b_system_search_show
  • b_system_themes_edit
  • b_system_themes_show
  • b_system_topposters_edit
  • b_system_topposters_show
  • b_system_user_show
  • b_system_waiting_show
  • bannerstats
  • change_banner_url_by_client
  • checkEmail
  • clickbanner
  • clientlogin
  • closeTable
  • closeThread
  • CloseWaitBox
  • Composer\Autoload\includeFile
  • composerRequire274e5fff219a4f27a346e611b0580d6a
  • createConfigform
  • createThemeform
  • doConditionalGet
  • emailStats
  • exit404BadReq
  • fatalPhpErrorHandler
  • file_get_contents
  • file_put_contents
  • findSharp
  • form_user
  • formatTimestamp
  • formatURL
  • gd_info
  • genPathCheckHtml
  • get_request_method
  • get_writeoks_from_protector
  • getcss
  • getDbCharsets
  • getDbCollations
  • getDirList
  • getMailer
  • getTheme
  • gif_getSize
  • gif_loadFile
  • gif_loadFileToGDimageResource
  • gif_outputAsBmp
  • gif_outputAsJpeg
  • gif_outputAsPng
  • HTMLPurifier
  • imagealphablending
  • imageBrowser
  • imageCreateCorners
  • imageFilenameCheck
  • imagesavealpha
  • install_acceptUser
  • install_finalize
  • is_executable
  • kses
  • langDropdown
  • load_functions
  • load_object
  • load_objectHandler
  • loadModuleAdminMenu
  • make_cblock
  • make_data
  • make_groups
  • make_sidebar
  • mod_clearCacheFile
  • mod_clearConfg
  • mod_clearConfig
  • mod_clearFile
  • mod_clearSmartyCache
  • mod_constant
  • mod_createCacheFile
  • mod_createCacheFile_byGroup
  • mod_createFile
  • mod_DB_prefix
  • mod_fetchConfg
  • mod_fetchConfig
  • mod_generateCacheId
  • mod_generateCacheId_byGroup
  • mod_getDirname
  • mod_getIP
  • mod_getMysqlVersion
  • mod_getUnameFromId
  • mod_getUnameFromIds
  • mod_isModuleAction
  • mod_loadCacheFile
  • mod_loadCacheFile_byGroup
  • mod_loadConfg
  • mod_loadConfig
  • mod_loadFile
  • mod_loadFunctions
  • mod_loadRenderer
  • mod_message
  • modify_chmod
  • myTextForm
  • notificationCategoryInfo
  • notificationCommentCategoryInfo
  • notificationEnabled
  • notificationEventEnabled
  • notificationEventInfo
  • notificationEvents
  • notificationGenerateConfig
  • notificationSubscribableCategoryInfo
  • openTable
  • openThread
  • OpenWaitBox
  • PHPMailerAutoload
  • phpThumbURL
  • preg_quote
  • profile_getFieldForm
  • profile_getRegisterForm
  • profile_getStepForm
  • profile_getUserForm
  • profile_install_addCategory
  • profile_install_addField
  • profile_install_addStep
  • profile_install_initializeProfiles
  • profile_install_setPermissions
  • protector_message_append_oninstall
  • protector_message_append_onuninstall
  • protector_message_append_onupdate
  • protector_notify_base
  • protector_oninstall_base
  • protector_onuninstall_base
  • protector_onupdate_base
  • protector_postcommon
  • protector_prepare
  • recaptcha_check_answer
  • recaptcha_get_html
  • recaptcha_get_signup_url
  • recaptcha_mailhide_html
  • recaptcha_mailhide_url
  • redirect_header
  • RedirectToCachedFile
  • SendSaveAsFileHeaderIfNeeded
  • showbanner
  • showThread
  • smarty_block_textformat
  • smarty_compiler_assign
  • smarty_compiler_foreachq
  • smarty_compiler_includeq
  • smarty_compiler_xoAdminIcons
  • smarty_compiler_xoAdminNav
  • smarty_compiler_xoAppUrl
  • smarty_compiler_xoImgUrl
  • smarty_compiler_xoModuleIcons16
  • smarty_compiler_xoModuleIcons32
  • smarty_compiler_xoModuleIconsBookmarks
  • smarty_core_assemble_plugin_filepath
  • smarty_core_assign_smarty_interface
  • smarty_core_create_dir_structure
  • smarty_core_display_debug_console
  • smarty_core_get_include_path
  • smarty_core_get_microtime
  • smarty_core_get_php_resource
  • smarty_core_is_secure
  • smarty_core_is_trusted
  • smarty_core_load_plugins
  • smarty_core_load_resource_plugin
  • smarty_core_process_cached_inserts
  • smarty_core_process_compiled_include
  • smarty_core_read_cache_file
  • smarty_core_rm_auto
  • smarty_core_rmdir
  • smarty_core_run_insert_handler
  • smarty_core_smarty_include_php
  • smarty_core_write_cache_file
  • smarty_core_write_compiled_include
  • smarty_core_write_compiled_resource
  • smarty_core_write_file
  • smarty_function_assign_debug_info
  • smarty_function_block
  • smarty_function_config_load
  • smarty_function_counter
  • smarty_function_cycle
  • smarty_function_debug
  • smarty_function_escape_special_chars
  • smarty_function_eval
  • smarty_function_fetch
  • smarty_function_html_checkboxes
  • smarty_function_html_checkboxes_output
  • smarty_function_html_image
  • smarty_function_html_options
  • smarty_function_html_options_optgroup
  • smarty_function_html_options_optoutput
  • smarty_function_html_radios
  • smarty_function_html_radios_output
  • smarty_function_html_select_date
  • smarty_function_html_select_time
  • smarty_function_html_table
  • smarty_function_html_table_cycle
  • smarty_function_mailto
  • smarty_function_math
  • smarty_function_popup
  • smarty_function_popup_init
  • smarty_function_securityToken
  • smarty_function_xoInboxCount
  • smarty_function_xoMemberInfo
  • smarty_function_xoops_link
  • smarty_function_xoPageNav
  • smarty_make_timestamp
  • smarty_modifier_capitalize
  • smarty_modifier_capitalize_ucfirst
  • smarty_modifier_cat
  • smarty_modifier_count_characters
  • smarty_modifier_count_paragraphs
  • smarty_modifier_count_sentences
  • smarty_modifier_count_words
  • smarty_modifier_date_format
  • smarty_modifier_debug_print_var
  • smarty_modifier_default
  • smarty_modifier_escape
  • smarty_modifier_indent
  • smarty_modifier_lower
  • smarty_modifier_nl2br
  • smarty_modifier_regex_replace
  • smarty_modifier_replace
  • smarty_modifier_spacify
  • smarty_modifier_string_format
  • smarty_modifier_strip
  • smarty_modifier_strip_tags
  • smarty_modifier_truncate
  • smarty_modifier_upper
  • smarty_modifier_wordwrap
  • smarty_outputfilter_trimwhitespace
  • smarty_outputfilter_trimwhitespace_replace
  • smarty_resource_db_secure
  • smarty_resource_db_source
  • smarty_resource_db_timestamp
  • smarty_resource_db_tplinfo
  • smarty_resource_db_trusted
  • synchronize
  • system_AdminIcons
  • system_adminVersion
  • system_CleanVars
  • system_loadLanguage
  • system_loadTemplate
  • themecenterposts
  • update_system_v211
  • userCheck
  • userTimeToServerTime
  • validateDbCharset
  • writeLicenseKey
  • xoBuildLicenceKey
  • xoDiag
  • xoDiagBoolSetting
  • xoDiagIfWritable
  • xoFormBlockCollation
  • xoFormField
  • xoFormFieldCharset
  • xoFormFieldCollation
  • xoFormSelect
  • xoops_aw_decode
  • xoops_aw_encode
  • xoops_bin2hex
  • xoops_comment_count
  • xoops_comment_delete
  • xoops_confirm
  • xoops_convert_decode
  • xoops_convert_encode
  • xoops_convert_encoding
  • xoops_cp_footer
  • xoops_cp_header
  • xoops_error
  • xoops_footer
  • xoops_getActiveModules
  • xoops_getbanner
  • xoops_getBaseDomain
  • xoops_getConfigOption
  • xoops_getcss
  • xoops_getenv
  • xoops_getHandler
  • xoops_getLinkedUnameFromId
  • xoops_getMailer
  • xoops_getModuleHandler
  • xoops_getModuleOption
  • xoops_getOption
  • xoops_getrank
  • xoops_getUrlDomain
  • xoops_getUserTimestamp
  • xoops_groupperm_deletebymoditem
  • xoops_header
  • xoops_hex2bin
  • xoops_isActiveModule
  • xoops_ishexstr
  • xoops_load
  • xoops_load_lang_file
  • xoops_loadLanguage
  • xoops_local
  • xoops_makepass
  • xoops_message
  • xoops_module_activate
  • xoops_module_change
  • xoops_module_deactivate
  • xoops_module_delayed_clean_cache
  • xoops_module_get_admin_menu
  • xoops_module_gettemplate
  • xoops_module_install
  • xoops_module_install_pm
  • xoops_module_install_profile
  • xoops_module_log_header
  • xoops_module_uninstall
  • xoops_module_update
  • xoops_module_update_pm
  • xoops_module_update_profile
  • xoops_module_update_system
  • xoops_module_write_admin_menu
  • xoops_notification_deletebyitem
  • xoops_notification_deletebymodule
  • xoops_notification_deletebyuser
  • xoops_refcheck
  • xoops_result
  • xoops_setActiveModules
  • xoops_setConfigOption
  • xoops_substr
  • xoops_template_clear_module_cache
  • xoops_template_touch
  • xoops_trim
  • xoops_utf8_encode
  • xoops_write_index_file
  • xoopsCodeTarea
  • xoopseditor_get_rootpath
  • XoopsErrorHandler_HandleError
  • xoopsfwrite
  • xoopsSmilies
  • xoPassField
  • xoPhpVersion
  • xoPutLicenseKey
  • xoStripeKey
  • Overview
  • Namespace
  • Class
  • Tree
   1: <?php
   2: /**
   3:  * PHPMailer RFC821 SMTP email transport class.
   4:  * PHP Version 5
   5:  * @package PHPMailer
   6:  * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
   7:  * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
   8:  * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
   9:  * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  10:  * @author Brent R. Matzelle (original founder)
  11:  * @copyright 2014 Marcus Bointon
  12:  * @copyright 2010 - 2012 Jim Jagielski
  13:  * @copyright 2004 - 2009 Andy Prevost
  14:  * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  15:  * @note This program is distributed in the hope that it will be useful - WITHOUT
  16:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17:  * FITNESS FOR A PARTICULAR PURPOSE.
  18:  */
  19: 
  20: /**
  21:  * PHPMailer RFC821 SMTP email transport class.
  22:  * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server.
  23:  * @package PHPMailer
  24:  * @author Chris Ryan
  25:  * @author Marcus Bointon <phpmailer@synchromedia.co.uk>
  26:  */
  27: class SMTP
  28: {
  29:     /**
  30:      * The PHPMailer SMTP version number.
  31:      * @var string
  32:      */
  33:     const VERSION = '5.2.21';
  34: 
  35:     /**
  36:      * SMTP line break constant.
  37:      * @var string
  38:      */
  39:     const CRLF = "\r\n";
  40: 
  41:     /**
  42:      * The SMTP port to use if one is not specified.
  43:      * @var integer
  44:      */
  45:     const DEFAULT_SMTP_PORT = 25;
  46: 
  47:     /**
  48:      * The maximum line length allowed by RFC 2822 section 2.1.1
  49:      * @var integer
  50:      */
  51:     const MAX_LINE_LENGTH = 998;
  52: 
  53:     /**
  54:      * Debug level for no output
  55:      */
  56:     const DEBUG_OFF = 0;
  57: 
  58:     /**
  59:      * Debug level to show client -> server messages
  60:      */
  61:     const DEBUG_CLIENT = 1;
  62: 
  63:     /**
  64:      * Debug level to show client -> server and server -> client messages
  65:      */
  66:     const DEBUG_SERVER = 2;
  67: 
  68:     /**
  69:      * Debug level to show connection status, client -> server and server -> client messages
  70:      */
  71:     const DEBUG_CONNECTION = 3;
  72: 
  73:     /**
  74:      * Debug level to show all messages
  75:      */
  76:     const DEBUG_LOWLEVEL = 4;
  77: 
  78:     /**
  79:      * The PHPMailer SMTP Version number.
  80:      * @var string
  81:      * @deprecated Use the `VERSION` constant instead
  82:      * @see SMTP::VERSION
  83:      */
  84:     public $Version = '5.2.21';
  85: 
  86:     /**
  87:      * SMTP server port number.
  88:      * @var integer
  89:      * @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead
  90:      * @see SMTP::DEFAULT_SMTP_PORT
  91:      */
  92:     public $SMTP_PORT = 25;
  93: 
  94:     /**
  95:      * SMTP reply line ending.
  96:      * @var string
  97:      * @deprecated Use the `CRLF` constant instead
  98:      * @see SMTP::CRLF
  99:      */
 100:     public $CRLF = "\r\n";
 101: 
 102:     /**
 103:      * Debug output level.
 104:      * Options:
 105:      * * self::DEBUG_OFF (`0`) No debug output, default
 106:      * * self::DEBUG_CLIENT (`1`) Client commands
 107:      * * self::DEBUG_SERVER (`2`) Client commands and server responses
 108:      * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status
 109:      * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages
 110:      * @var integer
 111:      */
 112:     public $do_debug = self::DEBUG_OFF;
 113: 
 114:     /**
 115:      * How to handle debug output.
 116:      * Options:
 117:      * * `echo` Output plain-text as-is, appropriate for CLI
 118:      * * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
 119:      * * `error_log` Output to error log as configured in php.ini
 120:      *
 121:      * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
 122:      * <code>
 123:      * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
 124:      * </code>
 125:      * @var string|callable
 126:      */
 127:     public $Debugoutput = 'echo';
 128: 
 129:     /**
 130:      * Whether to use VERP.
 131:      * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
 132:      * @link http://www.postfix.org/VERP_README.html Info on VERP
 133:      * @var boolean
 134:      */
 135:     public $do_verp = false;
 136: 
 137:     /**
 138:      * The timeout value for connection, in seconds.
 139:      * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
 140:      * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure.
 141:      * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2
 142:      * @var integer
 143:      */
 144:     public $Timeout = 300;
 145: 
 146:     /**
 147:      * How long to wait for commands to complete, in seconds.
 148:      * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
 149:      * @var integer
 150:      */
 151:     public $Timelimit = 300;
 152: 
 153:     /**
 154:      * @var array patterns to extract smtp transaction id from smtp reply
 155:      * Only first capture group will be use, use non-capturing group to deal with it
 156:      * Extend this class to override this property to fulfil your needs.
 157:      */
 158:     protected $smtp_transaction_id_patterns = array(
 159:         'exim' => '/[0-9]{3} OK id=(.*)/',
 160:         'sendmail' => '/[0-9]{3} 2.0.0 (.*) Message/',
 161:         'postfix' => '/[0-9]{3} 2.0.0 Ok: queued as (.*)/'
 162:     );
 163: 
 164:     /**
 165:      * The socket for the server connection.
 166:      * @var resource
 167:      */
 168:     protected $smtp_conn;
 169: 
 170:     /**
 171:      * Error information, if any, for the last SMTP command.
 172:      * @var array
 173:      */
 174:     protected $error = array(
 175:         'error' => '',
 176:         'detail' => '',
 177:         'smtp_code' => '',
 178:         'smtp_code_ex' => ''
 179:     );
 180: 
 181:     /**
 182:      * The reply the server sent to us for HELO.
 183:      * If null, no HELO string has yet been received.
 184:      * @var string|null
 185:      */
 186:     protected $helo_rply = null;
 187: 
 188:     /**
 189:      * The set of SMTP extensions sent in reply to EHLO command.
 190:      * Indexes of the array are extension names.
 191:      * Value at index 'HELO' or 'EHLO' (according to command that was sent)
 192:      * represents the server name. In case of HELO it is the only element of the array.
 193:      * Other values can be boolean TRUE or an array containing extension options.
 194:      * If null, no HELO/EHLO string has yet been received.
 195:      * @var array|null
 196:      */
 197:     protected $server_caps = null;
 198: 
 199:     /**
 200:      * The most recent reply received from the server.
 201:      * @var string
 202:      */
 203:     protected $last_reply = '';
 204: 
 205:     /**
 206:      * Output debugging info via a user-selected method.
 207:      * @see SMTP::$Debugoutput
 208:      * @see SMTP::$do_debug
 209:      * @param string $str Debug string to output
 210:      * @param integer $level The debug level of this message; see DEBUG_* constants
 211:      * @return void
 212:      */
 213:     protected function edebug($str, $level = 0)
 214:     {
 215:         if ($level > $this->do_debug) {
 216:             return;
 217:         }
 218:         //Avoid clash with built-in function names
 219:         if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
 220:             call_user_func($this->Debugoutput, $str, $level);
 221:             return;
 222:         }
 223:         switch ($this->Debugoutput) {
 224:             case 'error_log':
 225:                 //Don't output, just log
 226:                 error_log($str);
 227:                 break;
 228:             case 'html':
 229:                 //Cleans up output a bit for a better looking, HTML-safe output
 230:                 echo htmlentities(
 231:                     preg_replace('/[\r\n]+/', '', $str),
 232:                     ENT_QUOTES,
 233:                     'UTF-8'
 234:                 )
 235:                 . "<br>\n";
 236:                 break;
 237:             case 'echo':
 238:             default:
 239:                 //Normalize line breaks
 240:                 $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
 241:                 echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
 242:                     "\n",
 243:                     "\n                   \t                  ",
 244:                     trim($str)
 245:                 )."\n";
 246:         }
 247:     }
 248: 
 249:     /**
 250:      * Connect to an SMTP server.
 251:      * @param string $host SMTP server IP or host name
 252:      * @param integer $port The port number to connect to
 253:      * @param integer $timeout How long to wait for the connection to open
 254:      * @param array $options An array of options for stream_context_create()
 255:      * @access public
 256:      * @return boolean
 257:      */
 258:     public function connect($host, $port = null, $timeout = 30, $options = array())
 259:     {
 260:         static $streamok;
 261:         //This is enabled by default since 5.0.0 but some providers disable it
 262:         //Check this once and cache the result
 263:         if (is_null($streamok)) {
 264:             $streamok = function_exists('stream_socket_client');
 265:         }
 266:         // Clear errors to avoid confusion
 267:         $this->setError('');
 268:         // Make sure we are __not__ connected
 269:         if ($this->connected()) {
 270:             // Already connected, generate error
 271:             $this->setError('Already connected to a server');
 272:             return false;
 273:         }
 274:         if (empty($port)) {
 275:             $port = self::DEFAULT_SMTP_PORT;
 276:         }
 277:         // Connect to the SMTP server
 278:         $this->edebug(
 279:             "Connection: opening to $host:$port, timeout=$timeout, options=".var_export($options, true),
 280:             self::DEBUG_CONNECTION
 281:         );
 282:         $errno = 0;
 283:         $errstr = '';
 284:         if ($streamok) {
 285:             $socket_context = stream_context_create($options);
 286:             set_error_handler(array($this, 'errorHandler'));
 287:             $this->smtp_conn = stream_socket_client(
 288:                 $host . ":" . $port,
 289:                 $errno,
 290:                 $errstr,
 291:                 $timeout,
 292:                 STREAM_CLIENT_CONNECT,
 293:                 $socket_context
 294:             );
 295:             restore_error_handler();
 296:         } else {
 297:             //Fall back to fsockopen which should work in more places, but is missing some features
 298:             $this->edebug(
 299:                 "Connection: stream_socket_client not available, falling back to fsockopen",
 300:                 self::DEBUG_CONNECTION
 301:             );
 302:             set_error_handler(array($this, 'errorHandler'));
 303:             $this->smtp_conn = fsockopen(
 304:                 $host,
 305:                 $port,
 306:                 $errno,
 307:                 $errstr,
 308:                 $timeout
 309:             );
 310:             restore_error_handler();
 311:         }
 312:         // Verify we connected properly
 313:         if (!is_resource($this->smtp_conn)) {
 314:             $this->setError(
 315:                 'Failed to connect to server',
 316:                 $errno,
 317:                 $errstr
 318:             );
 319:             $this->edebug(
 320:                 'SMTP ERROR: ' . $this->error['error']
 321:                 . ": $errstr ($errno)",
 322:                 self::DEBUG_CLIENT
 323:             );
 324:             return false;
 325:         }
 326:         $this->edebug('Connection: opened', self::DEBUG_CONNECTION);
 327:         // SMTP server can take longer to respond, give longer timeout for first read
 328:         // Windows does not have support for this timeout function
 329:         if (substr(PHP_OS, 0, 3) != 'WIN') {
 330:             $max = ini_get('max_execution_time');
 331:             // Don't bother if unlimited
 332:             if ($max != 0 && $timeout > $max) {
 333:                 @set_time_limit($timeout);
 334:             }
 335:             stream_set_timeout($this->smtp_conn, $timeout, 0);
 336:         }
 337:         // Get any announcement
 338:         $announce = $this->get_lines();
 339:         $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER);
 340:         return true;
 341:     }
 342: 
 343:     /**
 344:      * Initiate a TLS (encrypted) session.
 345:      * @access public
 346:      * @return boolean
 347:      */
 348:     public function startTLS()
 349:     {
 350:         if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
 351:             return false;
 352:         }
 353: 
 354:         //Allow the best TLS version(s) we can
 355:         $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
 356: 
 357:         //PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
 358:         //so add them back in manually if we can
 359:         if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
 360:             $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
 361:             $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
 362:         }
 363: 
 364:         // Begin encrypted connection
 365:         if (!stream_socket_enable_crypto(
 366:             $this->smtp_conn,
 367:             true,
 368:             $crypto_method
 369:         )) {
 370:             return false;
 371:         }
 372:         return true;
 373:     }
 374: 
 375:     /**
 376:      * Perform SMTP authentication.
 377:      * Must be run after hello().
 378:      * @see hello()
 379:      * @param string $username The user name
 380:      * @param string $password The password
 381:      * @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5, XOAUTH2)
 382:      * @param string $realm The auth realm for NTLM
 383:      * @param string $workstation The auth workstation for NTLM
 384:      * @param null|OAuth $OAuth An optional OAuth instance (@see PHPMailerOAuth)
 385:      * @return bool True if successfully authenticated.* @access public
 386:      */
 387:     public function authenticate(
 388:         $username,
 389:         $password,
 390:         $authtype = null,
 391:         $realm = '',
 392:         $workstation = '',
 393:         $OAuth = null
 394:     ) {
 395:         if (!$this->server_caps) {
 396:             $this->setError('Authentication is not allowed before HELO/EHLO');
 397:             return false;
 398:         }
 399: 
 400:         if (array_key_exists('EHLO', $this->server_caps)) {
 401:         // SMTP extensions are available. Let's try to find a proper authentication method
 402: 
 403:             if (!array_key_exists('AUTH', $this->server_caps)) {
 404:                 $this->setError('Authentication is not allowed at this stage');
 405:                 // 'at this stage' means that auth may be allowed after the stage changes
 406:                 // e.g. after STARTTLS
 407:                 return false;
 408:             }
 409: 
 410:             self::edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNKNOWN'), self::DEBUG_LOWLEVEL);
 411:             self::edebug(
 412:                 'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']),
 413:                 self::DEBUG_LOWLEVEL
 414:             );
 415: 
 416:             if (empty($authtype)) {
 417:                 foreach (array('CRAM-MD5', 'LOGIN', 'PLAIN', 'NTLM', 'XOAUTH2') as $method) {
 418:                     if (in_array($method, $this->server_caps['AUTH'])) {
 419:                         $authtype = $method;
 420:                         break;
 421:                     }
 422:                 }
 423:                 if (empty($authtype)) {
 424:                     $this->setError('No supported authentication methods found');
 425:                     return false;
 426:                 }
 427:                 self::edebug('Auth method selected: '.$authtype, self::DEBUG_LOWLEVEL);
 428:             }
 429: 
 430:             if (!in_array($authtype, $this->server_caps['AUTH'])) {
 431:                 $this->setError("The requested authentication method \"$authtype\" is not supported by the server");
 432:                 return false;
 433:             }
 434:         } elseif (empty($authtype)) {
 435:             $authtype = 'LOGIN';
 436:         }
 437:         switch ($authtype) {
 438:             case 'PLAIN':
 439:                 // Start authentication
 440:                 if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
 441:                     return false;
 442:                 }
 443:                 // Send encoded username and password
 444:                 if (!$this->sendCommand(
 445:                     'User & Password',
 446:                     base64_encode("\0" . $username . "\0" . $password),
 447:                     235
 448:                 )
 449:                 ) {
 450:                     return false;
 451:                 }
 452:                 break;
 453:             case 'LOGIN':
 454:                 // Start authentication
 455:                 if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
 456:                     return false;
 457:                 }
 458:                 if (!$this->sendCommand("Username", base64_encode($username), 334)) {
 459:                     return false;
 460:                 }
 461:                 if (!$this->sendCommand("Password", base64_encode($password), 235)) {
 462:                     return false;
 463:                 }
 464:                 break;
 465:             case 'XOAUTH2':
 466:                 //If the OAuth Instance is not set. Can be a case when PHPMailer is used
 467:                 //instead of PHPMailerOAuth
 468:                 if (is_null($OAuth)) {
 469:                     return false;
 470:                 }
 471:                 $oauth = $OAuth->getOauth64();
 472: 
 473:                 // Start authentication
 474:                 if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
 475:                     return false;
 476:                 }
 477:                 break;
 478:             case 'NTLM':
 479:                 /*
 480:                  * ntlm_sasl_client.php
 481:                  * Bundled with Permission
 482:                  *
 483:                  * How to telnet in windows:
 484:                  * http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
 485:                  * PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
 486:                  */
 487:                 require_once 'extras/ntlm_sasl_client.php';
 488:                 $temp = new stdClass;
 489:                 $ntlm_client = new ntlm_sasl_client_class;
 490:                 //Check that functions are available
 491:                 if (!$ntlm_client->initialize($temp)) {
 492:                     $this->setError($temp->error);
 493:                     $this->edebug(
 494:                         'You need to enable some modules in your php.ini file: '
 495:                         . $this->error['error'],
 496:                         self::DEBUG_CLIENT
 497:                     );
 498:                     return false;
 499:                 }
 500:                 //msg1
 501:                 $msg1 = $ntlm_client->typeMsg1($realm, $workstation); //msg1
 502: 
 503:                 if (!$this->sendCommand(
 504:                     'AUTH NTLM',
 505:                     'AUTH NTLM ' . base64_encode($msg1),
 506:                     334
 507:                 )
 508:                 ) {
 509:                     return false;
 510:                 }
 511:                 //Though 0 based, there is a white space after the 3 digit number
 512:                 //msg2
 513:                 $challenge = substr($this->last_reply, 3);
 514:                 $challenge = base64_decode($challenge);
 515:                 $ntlm_res = $ntlm_client->NTLMResponse(
 516:                     substr($challenge, 24, 8),
 517:                     $password
 518:                 );
 519:                 //msg3
 520:                 $msg3 = $ntlm_client->typeMsg3(
 521:                     $ntlm_res,
 522:                     $username,
 523:                     $realm,
 524:                     $workstation
 525:                 );
 526:                 // send encoded username
 527:                 return $this->sendCommand('Username', base64_encode($msg3), 235);
 528:             case 'CRAM-MD5':
 529:                 // Start authentication
 530:                 if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
 531:                     return false;
 532:                 }
 533:                 // Get the challenge
 534:                 $challenge = base64_decode(substr($this->last_reply, 4));
 535: 
 536:                 // Build the response
 537:                 $response = $username . ' ' . $this->hmac($challenge, $password);
 538: 
 539:                 // send encoded credentials
 540:                 return $this->sendCommand('Username', base64_encode($response), 235);
 541:             default:
 542:                 $this->setError("Authentication method \"$authtype\" is not supported");
 543:                 return false;
 544:         }
 545:         return true;
 546:     }
 547: 
 548:     /**
 549:      * Calculate an MD5 HMAC hash.
 550:      * Works like hash_hmac('md5', $data, $key)
 551:      * in case that function is not available
 552:      * @param string $data The data to hash
 553:      * @param string $key  The key to hash with
 554:      * @access protected
 555:      * @return string
 556:      */
 557:     protected function hmac($data, $key)
 558:     {
 559:         if (function_exists('hash_hmac')) {
 560:             return hash_hmac('md5', $data, $key);
 561:         }
 562: 
 563:         // The following borrowed from
 564:         // http://php.net/manual/en/function.mhash.php#27225
 565: 
 566:         // RFC 2104 HMAC implementation for php.
 567:         // Creates an md5 HMAC.
 568:         // Eliminates the need to install mhash to compute a HMAC
 569:         // by Lance Rushing
 570: 
 571:         $bytelen = 64; // byte length for md5
 572:         if (strlen($key) > $bytelen) {
 573:             $key = pack('H*', md5($key));
 574:         }
 575:         $key = str_pad($key, $bytelen, chr(0x00));
 576:         $ipad = str_pad('', $bytelen, chr(0x36));
 577:         $opad = str_pad('', $bytelen, chr(0x5c));
 578:         $k_ipad = $key ^ $ipad;
 579:         $k_opad = $key ^ $opad;
 580: 
 581:         return md5($k_opad . pack('H*', md5($k_ipad . $data)));
 582:     }
 583: 
 584:     /**
 585:      * Check connection state.
 586:      * @access public
 587:      * @return boolean True if connected.
 588:      */
 589:     public function connected()
 590:     {
 591:         if (is_resource($this->smtp_conn)) {
 592:             $sock_status = stream_get_meta_data($this->smtp_conn);
 593:             if ($sock_status['eof']) {
 594:                 // The socket is valid but we are not connected
 595:                 $this->edebug(
 596:                     'SMTP NOTICE: EOF caught while checking if connected',
 597:                     self::DEBUG_CLIENT
 598:                 );
 599:                 $this->close();
 600:                 return false;
 601:             }
 602:             return true; // everything looks good
 603:         }
 604:         return false;
 605:     }
 606: 
 607:     /**
 608:      * Close the socket and clean up the state of the class.
 609:      * Don't use this function without first trying to use QUIT.
 610:      * @see quit()
 611:      * @access public
 612:      * @return void
 613:      */
 614:     public function close()
 615:     {
 616:         $this->setError('');
 617:         $this->server_caps = null;
 618:         $this->helo_rply = null;
 619:         if (is_resource($this->smtp_conn)) {
 620:             // close the connection and cleanup
 621:             fclose($this->smtp_conn);
 622:             $this->smtp_conn = null; //Makes for cleaner serialization
 623:             $this->edebug('Connection: closed', self::DEBUG_CONNECTION);
 624:         }
 625:     }
 626: 
 627:     /**
 628:      * Send an SMTP DATA command.
 629:      * Issues a data command and sends the msg_data to the server,
 630:      * finializing the mail transaction. $msg_data is the message
 631:      * that is to be send with the headers. Each header needs to be
 632:      * on a single line followed by a <CRLF> with the message headers
 633:      * and the message body being separated by and additional <CRLF>.
 634:      * Implements rfc 821: DATA <CRLF>
 635:      * @param string $msg_data Message data to send
 636:      * @access public
 637:      * @return boolean
 638:      */
 639:     public function data($msg_data)
 640:     {
 641:         //This will use the standard timelimit
 642:         if (!$this->sendCommand('DATA', 'DATA', 354)) {
 643:             return false;
 644:         }
 645: 
 646:         /* The server is ready to accept data!
 647:          * According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF)
 648:          * so we will break the data up into lines by \r and/or \n then if needed we will break each of those into
 649:          * smaller lines to fit within the limit.
 650:          * We will also look for lines that start with a '.' and prepend an additional '.'.
 651:          * NOTE: this does not count towards line-length limit.
 652:          */
 653: 
 654:         // Normalize line breaks before exploding
 655:         $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data));
 656: 
 657:         /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
 658:          * of the first line (':' separated) does not contain a space then it _should_ be a header and we will
 659:          * process all lines before a blank line as headers.
 660:          */
 661: 
 662:         $field = substr($lines[0], 0, strpos($lines[0], ':'));
 663:         $in_headers = false;
 664:         if (!empty($field) && strpos($field, ' ') === false) {
 665:             $in_headers = true;
 666:         }
 667: 
 668:         foreach ($lines as $line) {
 669:             $lines_out = array();
 670:             if ($in_headers and $line == '') {
 671:                 $in_headers = false;
 672:             }
 673:             //Break this line up into several smaller lines if it's too long
 674:             //Micro-optimisation: isset($str[$len]) is faster than (strlen($str) > $len),
 675:             while (isset($line[self::MAX_LINE_LENGTH])) {
 676:                 //Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on
 677:                 //so as to avoid breaking in the middle of a word
 678:                 $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
 679:                 //Deliberately matches both false and 0
 680:                 if (!$pos) {
 681:                     //No nice break found, add a hard break
 682:                     $pos = self::MAX_LINE_LENGTH - 1;
 683:                     $lines_out[] = substr($line, 0, $pos);
 684:                     $line = substr($line, $pos);
 685:                 } else {
 686:                     //Break at the found point
 687:                     $lines_out[] = substr($line, 0, $pos);
 688:                     //Move along by the amount we dealt with
 689:                     $line = substr($line, $pos + 1);
 690:                 }
 691:                 //If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1
 692:                 if ($in_headers) {
 693:                     $line = "\t" . $line;
 694:                 }
 695:             }
 696:             $lines_out[] = $line;
 697: 
 698:             //Send the lines to the server
 699:             foreach ($lines_out as $line_out) {
 700:                 //RFC2821 section 4.5.2
 701:                 if (!empty($line_out) and $line_out[0] == '.') {
 702:                     $line_out = '.' . $line_out;
 703:                 }
 704:                 $this->client_send($line_out . self::CRLF);
 705:             }
 706:         }
 707: 
 708:         //Message data has been sent, complete the command
 709:         //Increase timelimit for end of DATA command
 710:         $savetimelimit = $this->Timelimit;
 711:         $this->Timelimit = $this->Timelimit * 2;
 712:         $result = $this->sendCommand('DATA END', '.', 250);
 713:         //Restore timelimit
 714:         $this->Timelimit = $savetimelimit;
 715:         return $result;
 716:     }
 717: 
 718:     /**
 719:      * Send an SMTP HELO or EHLO command.
 720:      * Used to identify the sending server to the receiving server.
 721:      * This makes sure that client and server are in a known state.
 722:      * Implements RFC 821: HELO <SP> <domain> <CRLF>
 723:      * and RFC 2821 EHLO.
 724:      * @param string $host The host name or IP to connect to
 725:      * @access public
 726:      * @return boolean
 727:      */
 728:     public function hello($host = '')
 729:     {
 730:         //Try extended hello first (RFC 2821)
 731:         return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host));
 732:     }
 733: 
 734:     /**
 735:      * Send an SMTP HELO or EHLO command.
 736:      * Low-level implementation used by hello()
 737:      * @see hello()
 738:      * @param string $hello The HELO string
 739:      * @param string $host The hostname to say we are
 740:      * @access protected
 741:      * @return boolean
 742:      */
 743:     protected function sendHello($hello, $host)
 744:     {
 745:         $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
 746:         $this->helo_rply = $this->last_reply;
 747:         if ($noerror) {
 748:             $this->parseHelloFields($hello);
 749:         } else {
 750:             $this->server_caps = null;
 751:         }
 752:         return $noerror;
 753:     }
 754: 
 755:     /**
 756:      * Parse a reply to HELO/EHLO command to discover server extensions.
 757:      * In case of HELO, the only parameter that can be discovered is a server name.
 758:      * @access protected
 759:      * @param string $type - 'HELO' or 'EHLO'
 760:      */
 761:     protected function parseHelloFields($type)
 762:     {
 763:         $this->server_caps = array();
 764:         $lines = explode("\n", $this->helo_rply);
 765: 
 766:         foreach ($lines as $n => $s) {
 767:             //First 4 chars contain response code followed by - or space
 768:             $s = trim(substr($s, 4));
 769:             if (empty($s)) {
 770:                 continue;
 771:             }
 772:             $fields = explode(' ', $s);
 773:             if (!empty($fields)) {
 774:                 if (!$n) {
 775:                     $name = $type;
 776:                     $fields = $fields[0];
 777:                 } else {
 778:                     $name = array_shift($fields);
 779:                     switch ($name) {
 780:                         case 'SIZE':
 781:                             $fields = ($fields ? $fields[0] : 0);
 782:                             break;
 783:                         case 'AUTH':
 784:                             if (!is_array($fields)) {
 785:                                 $fields = array();
 786:                             }
 787:                             break;
 788:                         default:
 789:                             $fields = true;
 790:                     }
 791:                 }
 792:                 $this->server_caps[$name] = $fields;
 793:             }
 794:         }
 795:     }
 796: 
 797:     /**
 798:      * Send an SMTP MAIL command.
 799:      * Starts a mail transaction from the email address specified in
 800:      * $from. Returns true if successful or false otherwise. If True
 801:      * the mail transaction is started and then one or more recipient
 802:      * commands may be called followed by a data command.
 803:      * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
 804:      * @param string $from Source address of this message
 805:      * @access public
 806:      * @return boolean
 807:      */
 808:     public function mail($from)
 809:     {
 810:         $useVerp = ($this->do_verp ? ' XVERP' : '');
 811:         return $this->sendCommand(
 812:             'MAIL FROM',
 813:             'MAIL FROM:<' . $from . '>' . $useVerp,
 814:             250
 815:         );
 816:     }
 817: 
 818:     /**
 819:      * Send an SMTP QUIT command.
 820:      * Closes the socket if there is no error or the $close_on_error argument is true.
 821:      * Implements from rfc 821: QUIT <CRLF>
 822:      * @param boolean $close_on_error Should the connection close if an error occurs?
 823:      * @access public
 824:      * @return boolean
 825:      */
 826:     public function quit($close_on_error = true)
 827:     {
 828:         $noerror = $this->sendCommand('QUIT', 'QUIT', 221);
 829:         $err = $this->error; //Save any error
 830:         if ($noerror or $close_on_error) {
 831:             $this->close();
 832:             $this->error = $err; //Restore any error from the quit command
 833:         }
 834:         return $noerror;
 835:     }
 836: 
 837:     /**
 838:      * Send an SMTP RCPT command.
 839:      * Sets the TO argument to $toaddr.
 840:      * Returns true if the recipient was accepted false if it was rejected.
 841:      * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
 842:      * @param string $address The address the message is being sent to
 843:      * @access public
 844:      * @return boolean
 845:      */
 846:     public function recipient($address)
 847:     {
 848:         return $this->sendCommand(
 849:             'RCPT TO',
 850:             'RCPT TO:<' . $address . '>',
 851:             array(250, 251)
 852:         );
 853:     }
 854: 
 855:     /**
 856:      * Send an SMTP RSET command.
 857:      * Abort any transaction that is currently in progress.
 858:      * Implements rfc 821: RSET <CRLF>
 859:      * @access public
 860:      * @return boolean True on success.
 861:      */
 862:     public function reset()
 863:     {
 864:         return $this->sendCommand('RSET', 'RSET', 250);
 865:     }
 866: 
 867:     /**
 868:      * Send a command to an SMTP server and check its return code.
 869:      * @param string $command The command name - not sent to the server
 870:      * @param string $commandstring The actual command to send
 871:      * @param integer|array $expect One or more expected integer success codes
 872:      * @access protected
 873:      * @return boolean True on success.
 874:      */
 875:     protected function sendCommand($command, $commandstring, $expect)
 876:     {
 877:         if (!$this->connected()) {
 878:             $this->setError("Called $command without being connected");
 879:             return false;
 880:         }
 881:         //Reject line breaks in all commands
 882:         if (strpos($commandstring, "\n") !== false or strpos($commandstring, "\r") !== false) {
 883:             $this->setError("Command '$command' contained line breaks");
 884:             return false;
 885:         }
 886:         $this->client_send($commandstring . self::CRLF);
 887: 
 888:         $this->last_reply = $this->get_lines();
 889:         // Fetch SMTP code and possible error code explanation
 890:         $matches = array();
 891:         if (preg_match("/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/", $this->last_reply, $matches)) {
 892:             $code = $matches[1];
 893:             $code_ex = (count($matches) > 2 ? $matches[2] : null);
 894:             // Cut off error code from each response line
 895:             $detail = preg_replace(
 896:                 "/{$code}[ -]".($code_ex ? str_replace('.', '\\.', $code_ex).' ' : '')."/m",
 897:                 '',
 898:                 $this->last_reply
 899:             );
 900:         } else {
 901:             // Fall back to simple parsing if regex fails
 902:             $code = substr($this->last_reply, 0, 3);
 903:             $code_ex = null;
 904:             $detail = substr($this->last_reply, 4);
 905:         }
 906: 
 907:         $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
 908: 
 909:         if (!in_array($code, (array)$expect)) {
 910:             $this->setError(
 911:                 "$command command failed",
 912:                 $detail,
 913:                 $code,
 914:                 $code_ex
 915:             );
 916:             $this->edebug(
 917:                 'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply,
 918:                 self::DEBUG_CLIENT
 919:             );
 920:             return false;
 921:         }
 922: 
 923:         $this->setError('');
 924:         return true;
 925:     }
 926: 
 927:     /**
 928:      * Send an SMTP SAML command.
 929:      * Starts a mail transaction from the email address specified in $from.
 930:      * Returns true if successful or false otherwise. If True
 931:      * the mail transaction is started and then one or more recipient
 932:      * commands may be called followed by a data command. This command
 933:      * will send the message to the users terminal if they are logged
 934:      * in and send them an email.
 935:      * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
 936:      * @param string $from The address the message is from
 937:      * @access public
 938:      * @return boolean
 939:      */
 940:     public function sendAndMail($from)
 941:     {
 942:         return $this->sendCommand('SAML', "SAML FROM:$from", 250);
 943:     }
 944: 
 945:     /**
 946:      * Send an SMTP VRFY command.
 947:      * @param string $name The name to verify
 948:      * @access public
 949:      * @return boolean
 950:      */
 951:     public function verify($name)
 952:     {
 953:         return $this->sendCommand('VRFY', "VRFY $name", array(250, 251));
 954:     }
 955: 
 956:     /**
 957:      * Send an SMTP NOOP command.
 958:      * Used to keep keep-alives alive, doesn't actually do anything
 959:      * @access public
 960:      * @return boolean
 961:      */
 962:     public function noop()
 963:     {
 964:         return $this->sendCommand('NOOP', 'NOOP', 250);
 965:     }
 966: 
 967:     /**
 968:      * Send an SMTP TURN command.
 969:      * This is an optional command for SMTP that this class does not support.
 970:      * This method is here to make the RFC821 Definition complete for this class
 971:      * and _may_ be implemented in future
 972:      * Implements from rfc 821: TURN <CRLF>
 973:      * @access public
 974:      * @return boolean
 975:      */
 976:     public function turn()
 977:     {
 978:         $this->setError('The SMTP TURN command is not implemented');
 979:         $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT);
 980:         return false;
 981:     }
 982: 
 983:     /**
 984:      * Send raw data to the server.
 985:      * @param string $data The data to send
 986:      * @access public
 987:      * @return integer|boolean The number of bytes sent to the server or false on error
 988:      */
 989:     public function client_send($data)
 990:     {
 991:         $this->edebug("CLIENT -> SERVER: $data", self::DEBUG_CLIENT);
 992:         return fwrite($this->smtp_conn, $data);
 993:     }
 994: 
 995:     /**
 996:      * Get the latest error.
 997:      * @access public
 998:      * @return array
 999:      */
1000:     public function getError()
1001:     {
1002:         return $this->error;
1003:     }
1004: 
1005:     /**
1006:      * Get SMTP extensions available on the server
1007:      * @access public
1008:      * @return array|null
1009:      */
1010:     public function getServerExtList()
1011:     {
1012:         return $this->server_caps;
1013:     }
1014: 
1015:     /**
1016:      * A multipurpose method
1017:      * The method works in three ways, dependent on argument value and current state
1018:      *   1. HELO/EHLO was not sent - returns null and set up $this->error
1019:      *   2. HELO was sent
1020:      *     $name = 'HELO': returns server name
1021:      *     $name = 'EHLO': returns boolean false
1022:      *     $name = any string: returns null and set up $this->error
1023:      *   3. EHLO was sent
1024:      *     $name = 'HELO'|'EHLO': returns server name
1025:      *     $name = any string: if extension $name exists, returns boolean True
1026:      *       or its options. Otherwise returns boolean False
1027:      * In other words, one can use this method to detect 3 conditions:
1028:      *  - null returned: handshake was not or we don't know about ext (refer to $this->error)
1029:      *  - false returned: the requested feature exactly not exists
1030:      *  - positive value returned: the requested feature exists
1031:      * @param string $name Name of SMTP extension or 'HELO'|'EHLO'
1032:      * @return mixed
1033:      */
1034:     public function getServerExt($name)
1035:     {
1036:         if (!$this->server_caps) {
1037:             $this->setError('No HELO/EHLO was sent');
1038:             return null;
1039:         }
1040: 
1041:         // the tight logic knot ;)
1042:         if (!array_key_exists($name, $this->server_caps)) {
1043:             if ($name == 'HELO') {
1044:                 return $this->server_caps['EHLO'];
1045:             }
1046:             if ($name == 'EHLO' || array_key_exists('EHLO', $this->server_caps)) {
1047:                 return false;
1048:             }
1049:             $this->setError('HELO handshake was used. Client knows nothing about server extensions');
1050:             return null;
1051:         }
1052: 
1053:         return $this->server_caps[$name];
1054:     }
1055: 
1056:     /**
1057:      * Get the last reply from the server.
1058:      * @access public
1059:      * @return string
1060:      */
1061:     public function getLastReply()
1062:     {
1063:         return $this->last_reply;
1064:     }
1065: 
1066:     /**
1067:      * Read the SMTP server's response.
1068:      * Either before eof or socket timeout occurs on the operation.
1069:      * With SMTP we can tell if we have more lines to read if the
1070:      * 4th character is '-' symbol. If it is a space then we don't
1071:      * need to read anything else.
1072:      * @access protected
1073:      * @return string
1074:      */
1075:     protected function get_lines()
1076:     {
1077:         // If the connection is bad, give up straight away
1078:         if (!is_resource($this->smtp_conn)) {
1079:             return '';
1080:         }
1081:         $data = '';
1082:         $endtime = 0;
1083:         stream_set_timeout($this->smtp_conn, $this->Timeout);
1084:         if ($this->Timelimit > 0) {
1085:             $endtime = time() + $this->Timelimit;
1086:         }
1087:         while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
1088:             $str = @fgets($this->smtp_conn, 515);
1089:             $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL);
1090:             $this->edebug("SMTP -> get_lines(): \$str is  \"$str\"", self::DEBUG_LOWLEVEL);
1091:             $data .= $str;
1092:             // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen
1093:             if ((isset($str[3]) and $str[3] == ' ')) {
1094:                 break;
1095:             }
1096:             // Timed-out? Log and break
1097:             $info = stream_get_meta_data($this->smtp_conn);
1098:             if ($info['timed_out']) {
1099:                 $this->edebug(
1100:                     'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)',
1101:                     self::DEBUG_LOWLEVEL
1102:                 );
1103:                 break;
1104:             }
1105:             // Now check if reads took too long
1106:             if ($endtime and time() > $endtime) {
1107:                 $this->edebug(
1108:                     'SMTP -> get_lines(): timelimit reached ('.
1109:                     $this->Timelimit . ' sec)',
1110:                     self::DEBUG_LOWLEVEL
1111:                 );
1112:                 break;
1113:             }
1114:         }
1115:         return $data;
1116:     }
1117: 
1118:     /**
1119:      * Enable or disable VERP address generation.
1120:      * @param boolean $enabled
1121:      */
1122:     public function setVerp($enabled = false)
1123:     {
1124:         $this->do_verp = $enabled;
1125:     }
1126: 
1127:     /**
1128:      * Get VERP address generation mode.
1129:      * @return boolean
1130:      */
1131:     public function getVerp()
1132:     {
1133:         return $this->do_verp;
1134:     }
1135: 
1136:     /**
1137:      * Set error messages and codes.
1138:      * @param string $message The error message
1139:      * @param string $detail Further detail on the error
1140:      * @param string $smtp_code An associated SMTP error code
1141:      * @param string $smtp_code_ex Extended SMTP code
1142:      */
1143:     protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '')
1144:     {
1145:         $this->error = array(
1146:             'error' => $message,
1147:             'detail' => $detail,
1148:             'smtp_code' => $smtp_code,
1149:             'smtp_code_ex' => $smtp_code_ex
1150:         );
1151:     }
1152: 
1153:     /**
1154:      * Set debug output method.
1155:      * @param string|callable $method The name of the mechanism to use for debugging output, or a callable to handle it.
1156:      */
1157:     public function setDebugOutput($method = 'echo')
1158:     {
1159:         $this->Debugoutput = $method;
1160:     }
1161: 
1162:     /**
1163:      * Get debug output method.
1164:      * @return string
1165:      */
1166:     public function getDebugOutput()
1167:     {
1168:         return $this->Debugoutput;
1169:     }
1170: 
1171:     /**
1172:      * Set debug output level.
1173:      * @param integer $level
1174:      */
1175:     public function setDebugLevel($level = 0)
1176:     {
1177:         $this->do_debug = $level;
1178:     }
1179: 
1180:     /**
1181:      * Get debug output level.
1182:      * @return integer
1183:      */
1184:     public function getDebugLevel()
1185:     {
1186:         return $this->do_debug;
1187:     }
1188: 
1189:     /**
1190:      * Set SMTP timeout.
1191:      * @param integer $timeout
1192:      */
1193:     public function setTimeout($timeout = 0)
1194:     {
1195:         $this->Timeout = $timeout;
1196:     }
1197: 
1198:     /**
1199:      * Get SMTP timeout.
1200:      * @return integer
1201:      */
1202:     public function getTimeout()
1203:     {
1204:         return $this->Timeout;
1205:     }
1206: 
1207:     /**
1208:      * Reports an error number and string.
1209:      * @param integer $errno The error number returned by PHP.
1210:      * @param string $errmsg The error message returned by PHP.
1211:      */
1212:     protected function errorHandler($errno, $errmsg)
1213:     {
1214:         $notice = 'Connection: Failed to connect to server.';
1215:         $this->setError(
1216:             $notice,
1217:             $errno,
1218:             $errmsg
1219:         );
1220:         $this->edebug(
1221:             $notice . ' Error number ' . $errno . '. "Error notice: ' . $errmsg,
1222:             self::DEBUG_CONNECTION
1223:         );
1224:     }
1225: 
1226:     /**
1227:      * Will return the ID of the last smtp transaction based on a list of patterns provided
1228:      * in SMTP::$smtp_transaction_id_patterns.
1229:      * If no reply has been received yet, it will return null.
1230:      * If no pattern has been matched, it will return false.
1231:      * @return bool|null|string
1232:      */
1233:     public function getLastTransactionID()
1234:     {
1235:         $reply = $this->getLastReply();
1236: 
1237:         if (empty($reply)) {
1238:             return null;
1239:         }
1240: 
1241:         foreach($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) {
1242:             if(preg_match($smtp_transaction_id_pattern, $reply, $matches)) {
1243:                 return $matches[1];
1244:             }
1245:         }
1246: 
1247:         return false;
1248:     }
1249: }
1250: 
API documentation generated by ApiGen