Overview

Packages

  • admin
  • classes
    • media
  • CodeIgniter
    • Libraries
  • core
  • functions
  • JSMin
  • None
  • OpenID
  • PHP
  • PHPMailer
  • plugins
    • admin
    • development
    • feed
    • mail
    • media
    • misc
    • seo
    • spam
    • uploader
    • users
    • zenpage
    • zenphoto
      • news
  • Services
    • JSON

Classes

  • _zp_captcha
  • _zp_HTML_cache
  • admin_approval
  • Album
  • AlbumBase
  • AlbumZip
  • AMFReader
  • AMFStream
  • AnyFile
  • AnyFile_Options
  • Auth_OpenID
  • Auth_OpenID_AlreadySigned
  • Auth_OpenID_AssociateRequest
  • Auth_OpenID_Association
  • Auth_OpenID_AuthRequest
  • Auth_OpenID_AX
  • Auth_OpenID_AX_AttrInfo
  • Auth_OpenID_AX_Error
  • Auth_OpenID_AX_FetchRequest
  • Auth_OpenID_AX_FetchResponse
  • Auth_OpenID_AX_KeyValueMessage
  • Auth_OpenID_AX_Message
  • Auth_OpenID_AX_StoreRequest
  • Auth_OpenID_AX_StoreResponse
  • Auth_OpenID_BcMathWrapper
  • Auth_OpenID_CancelResponse
  • Auth_OpenID_CheckAuthRequest
  • Auth_OpenID_CheckIDRequest
  • Auth_OpenID_Consumer
  • Auth_OpenID_ConsumerResponse
  • Auth_OpenID_CryptUtil
  • Auth_OpenID_DatabaseConnection
  • Auth_OpenID_Decoder
  • Auth_OpenID_DiffieHellman
  • Auth_OpenID_DiffieHellmanSHA1ConsumerSession
  • Auth_OpenID_DiffieHellmanSHA1ServerSession
  • Auth_OpenID_DiffieHellmanSHA256ConsumerSession
  • Auth_OpenID_DiffieHellmanSHA256ServerSession
  • Auth_OpenID_DumbStore
  • Auth_OpenID_Encoder
  • Auth_OpenID_EncodingError
  • Auth_OpenID_Extension
  • Auth_OpenID_FailureResponse
  • Auth_OpenID_FileStore
  • Auth_OpenID_GenericConsumer
  • Auth_OpenID_GmpMathWrapper
  • Auth_OpenID_KVForm
  • Auth_OpenID_MalformedReturnURL
  • Auth_OpenID_MalformedTrustRoot
  • Auth_OpenID_Mapping
  • Auth_OpenID_MathLibrary
  • Auth_OpenID_MDB2Store
  • Auth_OpenID_MemcachedStore
  • Auth_OpenID_Message
  • Auth_OpenID_MySQLStore
  • Auth_OpenID_NamespaceMap
  • Auth_OpenID_NoReturnToError
  • Auth_OpenID_OpenIDStore
  • Auth_OpenID_PAPE_Request
  • Auth_OpenID_PAPE_Response
  • Auth_OpenID_Parse
  • Auth_OpenID_PlainTextConsumerSession
  • Auth_OpenID_PlainTextServerSession
  • Auth_OpenID_PostgreSQLStore
  • Auth_OpenID_Request
  • Auth_OpenID_Server
  • Auth_OpenID_ServerError
  • Auth_OpenID_ServerErrorContainer
  • Auth_OpenID_ServerRequest
  • Auth_OpenID_ServerResponse
  • Auth_OpenID_ServiceEndpoint
  • Auth_OpenID_ServiceEndpointLoader
  • Auth_OpenID_SessionNegotiator
  • Auth_OpenID_SetupNeededResponse
  • Auth_OpenID_Signatory
  • Auth_OpenID_SigningEncoder
  • Auth_OpenID_SQLiteStore
  • Auth_OpenID_SQLStore
  • Auth_OpenID_SRegBase
  • Auth_OpenID_SRegRequest
  • Auth_OpenID_SRegResponse
  • Auth_OpenID_SuccessResponse
  • Auth_OpenID_TrustRoot
  • Auth_OpenID_TypeURIMismatch
  • Auth_OpenID_UntrustedReturnURL
  • Auth_OpenID_WebResponse
  • Auth_Yadis_Discovery
  • Auth_Yadis_DiscoveryResult
  • Auth_Yadis_dom
  • Auth_Yadis_domxml
  • Auth_Yadis_HTTPFetcher
  • Auth_Yadis_HTTPResponse
  • Auth_Yadis_Manager
  • Auth_Yadis_ManagerLoader
  • Auth_Yadis_ParanoidHTTPFetcher
  • Auth_Yadis_ParseHTML
  • Auth_Yadis_PHPSession
  • Auth_Yadis_PlainHTTPFetcher
  • Auth_Yadis_ProxyResolver
  • Auth_Yadis_Service
  • Auth_Yadis_SessionLoader
  • Auth_Yadis_XMLParser
  • Auth_Yadis_XRDS
  • Auth_Yadis_Yadis
  • auto_backup
  • AVCSequenceParameterSetReader
  • bxslider
  • cacheManager
  • cacheManagerFeed
  • CI_jsmin
  • CI_load
  • cloneZenphoto
  • codeIgniter_kludge
  • colorbox
  • Comment
  • comment_form
  • contactformOptions
  • crop_image
  • cycle
  • defaultCodeblocks
  • deprecated_functions
  • DownloadList
  • dynamic_locale
  • dynamicAlbum
  • elFinder_options
  • email_new_user
  • exampleMacros
  • external_auth
  • ExternalFeed
  • externalFeed_options
  • favorites
  • favoritesOptions
  • federated_logon
  • feed
  • fieldExtender
  • flag_thumbnail
  • Gallery
  • galleryArticles
  • getID3
  • getid3_aac
  • getid3_apetag
  • getid3_flv
  • getid3_handler
  • getid3_id3v1
  • getid3_id3v2
  • getid3_lib
  • getid3_lyrics3
  • getid3_mp3
  • getid3_mpeg
  • getid3_quicktime
  • getid3_swf
  • GoogleMap
  • Googlemaps
  • googleVerifyOptions
  • hitcounter
  • HTML
  • htmlmetatags
  • http_auth
  • Image
  • image_effects
  • internal_deprecations
  • ipBlocker
  • jcarousel
  • jPlayer
  • jplayer_options
  • jquery_rating
  • JSMin
  • lib_GD_Options
  • lib_Imagick_Options
  • lib_NoGraphics
  • MediaObject
  • menu_manager
  • MergedRSS
  • MergedRSSOptions
  • mobile
  • Mobile_Detect
  • mobileTheme
  • multipleLayoutOptions
  • null_seo
  • OAuthConsumer
  • OAuthDataStore
  • OAuthRequest
  • OAuthServer
  • OAuthSignatureMethod
  • OAuthSignatureMethod_HMAC_SHA1
  • OAuthSignatureMethod_PLAINTEXT
  • OAuthSignatureMethod_RSA_SHA1
  • OAuthToken
  • OAuthUtil
  • pagedThumbsNav
  • pagedthumbsOptions
  • PclZip
  • PersistentObject
  • PHPMailer
  • PlainText
  • POP3
  • print_album_menu
  • pseudoPlayer
  • publishContent
  • quota_manager
  • reCaptcha
  • ReCaptchaResponse
  • register_user
  • rewriteRules
  • rewriteTokens
  • RSS
  • RSS_internal_deprecations
  • rss_options
  • search_statistics
  • SearchEngine
  • security_logger
  • seo_locale
  • Services_JSON
  • Services_JSON_Error
  • setupexternalFeed
  • setupRSS
  • show_not_loggedin
  • sitemap
  • slideshow
  • SMTP
  • static_html_cache
  • tagsuggest
  • TextObject
  • TextObject_internal_deprecations
  • TextObject_Options
  • ThemeObject
  • themeSwitcher
  • tinymce4Options
  • tinyURL
  • Transientimage
  • tweet
  • TwitterOAuth
  • UploadHandler
  • user_expiry
  • user_groups
  • user_logout_options
  • userAddressFields
  • utf8
  • Video
  • Video_internal_deprecations
  • VideoObject_Options
  • viewer_size_image_options
  • WEBdocs
  • WEBdocs_Options
  • xmpMetadata
  • Zenpage
  • Zenpage_internal_deprecations
  • ZenpageCategory
  • zenpagecms
  • ZenpageItems
  • ZenpageNews
  • ZenpagePage
  • ZenpageRoot
  • Zenphoto_Administrator
  • Zenphoto_Authority
  • zenphoto_org_news
  • zenphoto_seo
  • zenphotoDonate
  • ZipStream
  • zp_PHPMailer
  • zpCaptcha
  • zpFunctions
  • zpLegacySpam
  • zpMutex
  • zpSimpleSpam
  • zpTrivialSpam

Exceptions

  • BadFunctionCallException
  • BadMethodCallException
  • Exception
  • getid3_exception
  • JSMin_UnterminatedCommentException
  • JSMin_UnterminatedRegExpException
  • JSMin_UnterminatedStringException
  • LogicException
  • OAuthExcept
  • phpmailerException

Functions

  • __autoload
  • _escape_xref
  • _recaptcha_aes_encrypt
  • _recaptcha_aes_pad
  • _recaptcha_http_post
  • _recaptcha_mailhide_email_parts
  • _recaptcha_mailhide_urlbase64
  • _recaptcha_qsencode
  • accessAllAlbums
  • add_context
  • addalbumsToDatabase
  • addCategoriesToDatabase
  • addGeoCoord
  • addItem
  • addPagesToDatabase
  • addPluginScript
  • addPluginType
  • addSubalbumMenus
  • admin_album_list
  • admin_securityChecks
  • admin_showupdate
  • adminPageNav
  • adminToolbox
  • albumNumber
  • applyMacros
  • Auth_OpenID_arrangeByType
  • Auth_OpenID_AX_checkAlias
  • Auth_OpenID_AX_toTypeURIs
  • Auth_OpenID_bestMatchingService
  • Auth_OpenID_checkFieldName
  • Auth_OpenID_checkSessionType
  • Auth_OpenID_checkTimestamp
  • Auth_OpenID_detectMathLibrary
  • Auth_OpenID_discover
  • Auth_OpenID_discoverURI
  • Auth_OpenID_discoverWithoutYadis
  • Auth_OpenID_discoverWithYadis
  • Auth_OpenID_discoverXRI
  • Auth_OpenID_extractReturnURL
  • Auth_OpenID_findOPLocalIdentifier
  • Auth_OpenID_getAllAssociationTypes
  • Auth_OpenID_getAllowedReturnURLs
  • Auth_OpenID_getAuthorityPattern
  • Auth_OpenID_getAvailableSessionTypes
  • Auth_OpenID_getDefaultAssociationOrder
  • Auth_OpenID_getDefaultGen
  • Auth_OpenID_getDefaultMod
  • Auth_OpenID_getDefaultNegotiator
  • Auth_OpenID_getEncodedPattern
  • Auth_OpenID_getEncryptedNegotiator
  • Auth_OpenID_getEscapeRE
  • Auth_OpenID_getMathLib
  • Auth_OpenID_getOnlyEncryptedOrder
  • Auth_OpenID_getOpenIDConsumerTypeURIs
  • Auth_OpenID_getOpenIDTypeName
  • Auth_OpenID_getOpenIDTypeURIs
  • Auth_OpenID_getOPOrUserServices
  • Auth_OpenID_getSecretSize
  • Auth_OpenID_getSessionTypes
  • Auth_OpenID_getSupportedAssociationTypes
  • Auth_OpenID_getUnreserved
  • Auth_OpenID_getURIPattern
  • Auth_OpenID_getURLIllegalCharRE
  • Auth_OpenID_HMACSHA1
  • Auth_OpenID_HMACSHA256
  • Auth_OpenID_include_init
  • Auth_OpenID_isError
  • Auth_OpenID_isOpenID1
  • Auth_OpenID_legacy_discover
  • Auth_OpenID_makeOpenIDEndpoints
  • Auth_OpenID_math_extensions
  • Auth_OpenID_mkNonce
  • Auth_OpenID_noMathSupport
  • Auth_OpenID_pct_encoded_replace
  • Auth_OpenID_pct_encoded_replace_unreserved
  • Auth_OpenID_registerNamespaceAlias
  • Auth_OpenID_remove_dot_segments
  • Auth_OpenID_removeNamespaceAlias
  • Auth_OpenID_returnToMatches
  • Auth_OpenID_setNoMathSupport
  • Auth_OpenID_SHA1
  • Auth_OpenID_SHA256
  • Auth_OpenID_splitNonce
  • Auth_OpenID_supportsSReg
  • Auth_OpenID_urinorm
  • Auth_OpenID_verifyReturnTo
  • Auth_Yadis_array_scramble
  • Auth_Yadis_escapeForIRI
  • Auth_Yadis_getCanonicalID
  • Auth_Yadis_getDefaultProxy
  • Auth_Yadis_getEscapeRE
  • Auth_Yadis_getIPrivateChars
  • Auth_Yadis_getNSMap
  • Auth_Yadis_getServiceEndpoints
  • Auth_Yadis_getSupportedExtensions
  • Auth_Yadis_getUCSChars
  • Auth_Yadis_getXMLParser
  • Auth_Yadis_getXRDExpiration
  • Auth_Yadis_getXrefRE
  • Auth_Yadis_getXRIAuthorities
  • Auth_Yadis_identifierScheme
  • Auth_Yadis_iriToURI
  • Auth_Yadis_pct_escape_unicode
  • Auth_Yadis_providerIsAuthoritative
  • Auth_Yadis_rootAuthority
  • Auth_Yadis_setDefaultParser
  • Auth_Yadis_startswith
  • Auth_Yadis_toIRINormal
  • Auth_Yadis_toURINormal
  • Auth_Yadis_XRI
  • Auth_Yadis_XRIAppendArgs
  • authorSelector
  • build_query
  • build_url
  • bulkActionRedirect
  • bulkTags
  • byteConvert
  • cacheImage
  • checkAccess
  • checkAlbumimagesort
  • checkAlbumParentid
  • checkAlbumPassword
  • checkChosenItemStatus
  • checkChosenMenuset
  • checked
  • checkFolder
  • checkForEmptyTitle
  • checkForGuest
  • checkForPage
  • checkForPassword
  • checkForUpdate
  • checkHitcounterDisplay
  • checkIfChecked
  • checkIfLockedNews
  • checkIfLockedPage
  • checkIfNew
  • checkInstall
  • checkLayoutUseForImages
  • checkNewsAccess
  • checkNewsCategoryPassword
  • checkObjectsThumb
  • checkPagePassword
  • checkPageValidity
  • checkParentLayouts
  • checkPublishDates
  • checkRequiredField
  • checkSelectedAlbum
  • checkSignature
  • cleanAlbum
  • cleanHTML
  • clearSitemapCache
  • clonedFrom
  • codeblocktabsJS
  • comment_form_addComment
  • comment_form_handle_comment
  • comment_form_PaginationJS
  • comment_form_postcomment
  • comment_form_print10Most
  • comment_form_visualEditor
  • commentFormUseCaptcha
  • commentReply
  • commentsAllowed
  • consolidatedEditMessages
  • copyLayoutSelection
  • copyThemeDirectory
  • countArticles
  • countCombiNews
  • createMenuIfNotExists
  • createRelatedItemsResultArray
  • cron_starter
  • currentRelativeURL
  • customOptions
  • dateDiff
  • datepickerJS
  • dateTimeConvert
  • db_affected_rows
  • db_close
  • db_collation
  • db_connect
  • db_count
  • db_create
  • db_create_table
  • db_error
  • db_fetch_assoc
  • db_fetch_row
  • db_free_result
  • db_getSQLmode
  • db_insert_id
  • db_LIKE_escape
  • db_list_fields
  • db_name
  • db_num_rows
  • db_permissions
  • db_quote
  • db_setSQLmode
  • db_show
  • db_software
  • db_table_update
  • db_truncate_table
  • debug404
  • debugLog
  • debugLogBacktrace
  • debugLogVar
  • defaultCodeblocks_codebox
  • deleteArticle
  • deleteCategory
  • deleteItem
  • deleteLayoutSelection
  • deletePage
  • deleteThemeDirectory
  • detect_fetcher
  • detect_math
  • detect_query_corruption
  • detect_random
  • detect_stores
  • detect_xml
  • dircopy
  • displayError
  • doIncludes
  • elFinder_admin_tabs
  • elFinder_tinymce
  • enableExtension
  • escape
  • executeRSS
  • exitZP
  • exposeZenPhotoInformations
  • extensionEnabled
  • fetchComments
  • filesystemToInternal
  • filter_extractReturnURL
  • filter_MatchesAnyOpenIDConsumerType
  • filter_MatchesAnyOpenIDType
  • filterImageQuery
  • fix_path_redirect
  • formatList
  • fullText
  • galleryAlbumsPerPage
  • genAlbumList
  • generateCaptcha
  • generateLanguageList
  • generateListFromArray
  • generateListFromFiles
  • generateRadiobuttonsFromArray
  • generateSitemapCacheFile
  • generateSitemapIndexCacheFile
  • generateUnorderedListFromArray
  • get_AnyFile_suffixes
  • get_context
  • get_filterScript
  • get_instance
  • get_language_string
  • getAdminThumb
  • getAlbumArray
  • getAlbumBreadcrumb
  • getAlbumBreadcrumbAdmin
  • getAlbumCustomData
  • getAlbumData
  • getAlbumDate
  • getAlbumDesc
  • getAlbumFolder
  • getAlbumGeodata
  • getAlbumId
  • getAlbumInherited
  • getAlbumLinkURL
  • getAlbumLocation
  • getAlbumPage
  • getAlbumPlace
  • getAlbumStatistic
  • getAlbumThumb
  • getAlbumTitle
  • getAlbumURL
  • getAllAccessibleAlbums
  • getAllAlbums
  • getAllArticleDates
  • getAllCategories
  • getAllDates
  • getAllowedTags
  • getAllSubAlbumIDs
  • getAllSubalbums
  • getAllTagsCount
  • getAllTagsFromAlbum
  • getAllTagsFromAlbum_multi_unique
  • getAllTagsFromZenpage
  • getAllTagsUnique
  • getAllTranslations
  • getAnnotatedAlbumTitle
  • getAnnotatedImageTitle
  • getArticles
  • getAuthor
  • getBare
  • getBareAlbumDesc
  • getBareAlbumTitle
  • getBareGalleryDesc
  • getBareGalleryTitle
  • getBareImageDesc
  • getBareImageTitle
  • getBareNewsAlbumTitle
  • getBareNewsTitle
  • getBarePageTitle
  • getCategory
  • getCategoryID
  • getCategoryLink
  • getCategoryParentID
  • getCategorySortOrder
  • getCategoryTitle
  • getCheckboxState
  • getCodeblock
  • getCombiNews
  • getCommentAddress
  • getCommentAuthorEmail
  • getCommentAuthorLink
  • getCommentAuthorName
  • getCommentAuthorSite
  • getCommentBody
  • getCommentCount
  • getCommentDate
  • getCommentDateTime
  • getCommentErrors
  • getCommentsAllowed
  • getCommentStored
  • getCommentTime
  • getConsumer
  • getContentShorten
  • getCurrentMenuItem
  • getCurrentNewsArchive
  • getCurrentNewsCategory
  • getCurrentNewsCategoryID
  • getCurrentNewsCategoryParentID
  • getCurrentNewsPage
  • getCurrentPage
  • getCurrentTheme
  • getCustomAlbumThumb
  • getCustomAlbumThumbMaxSpace
  • getCustomImageURL
  • getCustomPageURL
  • getCustomSizedImageMaxSpace
  • getCustomSizedImageThumbMaxSpace
  • getDefaultHeight
  • getDefaultSizedImage
  • getDefaultWidth
  • getDownloadLink
  • getdownloadList
  • getDownloadURL
  • getE
  • getEnabledPlugins
  • getExpiryDatePost
  • getFavoritesURL
  • getField
  • getFirstImageURL
  • getFullHeight
  • getFullImageURL
  • getFullNewsImage
  • getFullWidth
  • getGalleryDesc
  • getGalleryIndexURL
  • getGalleryTitle
  • getGeoCoord
  • getHeadTitle
  • getHitcounter
  • getImageArgs
  • getImageCacheFilename
  • getImageCachePostfix
  • getImageCity
  • getImageCountry
  • getImageCustomData
  • getImageData
  • getImageDate
  • getImageDesc
  • getImageEXIFData
  • getImageGeodata
  • getImageID
  • getImageLinkURL
  • getImageLocation
  • getImageMetaData
  • getImageParameters
  • getImageProcessorURI
  • getImageProcessorURIFromCacheName
  • getImageRotation
  • getImageSortOrder
  • getImageState
  • getImageStatistic
  • getImageThumb
  • getImageTitle
  • getImageURI
  • getImageURL
  • getItem
  • getItemByID
  • getItemTitleAndURL
  • getjPlayerSkinCSS
  • getjPlayerSkins
  • getLanguageArray
  • getLanguageFlag
  • getLastImageURL
  • getLatestComments
  • getLatestNews
  • getLatestZenpageComments
  • getLayout
  • getLayoutSelector
  • getLink
  • getLinkHTML
  • getLogTabs
  • getMacros
  • getMainSiteName
  • getMainSiteURL
  • getManagedAlbumList
  • getMaxSpaceContainer
  • getMenuFromLink
  • getMenuItemChilds
  • getMenuItems
  • getMenumanagerPredicessor
  • getMenumanagerSuccessor
  • getMenuSetSelector
  • getMenuVisibility
  • getMimeString
  • getNestedAlbumList
  • getNewsAdminOption
  • getNewsAdminOptionPath
  • getNewsAlbumName
  • getNewsAlbumTitle
  • getNewsAlbumURL
  • getNewsArchivePath
  • getNewsArchiveURL
  • getNewsAuthor
  • getNewsCategories
  • getNewsCategoryCustomData
  • getNewsCategoryDesc
  • getNewsCategoryPath
  • getNewsCategoryURL
  • getNewsContent
  • getNewsContentShorten
  • getNewsCustomData
  • getNewsDate
  • getNewsExtraContent
  • getNewsID
  • getNewsImageTags
  • getNewsIndexURL
  • getNewsLink
  • getNewsPagesStatistic
  • getNewsPathNav
  • getNewsReadMore
  • getNewsTitle
  • getNewsTitleLink
  • getNewsTitlePath
  • getNewsType
  • getNewsURL
  • getNewsVideoContent
  • getNextAlbum
  • getNextAlbumURL
  • getNextImageThumb
  • getNextImageURL
  • getNextNewsPageURL
  • getNextNewsURL
  • getNextPageURL
  • getNextPrevNews
  • getNotViewableAlbums
  • getNotViewableImages
  • getNumAlbums
  • getNumAllSubalbums
  • getNumImages
  • getNumNews
  • getNumPages
  • getNumSubalbums
  • getOpenIDURL
  • getOption
  • getOptionFromDB
  • getOptionList
  • getPageAuthor
  • getPageContent
  • getPageCustomData
  • getPageDate
  • getPageExtraContent
  • getPageID
  • getPageLastChangeDate
  • getPageLinkPath
  • getPageLinkURL
  • getPageNavList
  • getPageNumURL
  • getPageParentID
  • getPageRedirect
  • getPages
  • getPageSelector
  • getPageSortorder
  • getPageTitle
  • getPageTitleLink
  • getPageURL
  • getParentAlbums
  • getParentAlbumsAdmin
  • getParentBreadcrumb
  • getParentItems
  • getParentMenuItems
  • getParentNewsCategories
  • getParentPages
  • getPasswordProtectImage
  • getPHPFiles
  • getPlugin
  • getPluginFiles
  • getPluginTabs
  • getPrevAlbum
  • getPrevAlbumURL
  • getPrevImageThumb
  • getPrevImageURL
  • getPrevNewsPageURL
  • getPrevNewsURL
  • getPrevPageURL
  • getProtectedImageURL
  • getRandomImages
  • getRandomImagesAlbum
  • getRating
  • getRelatedItems
  • getRequestURI
  • getReturnTo
  • getRSSHeaderLink
  • getRSSLink
  • getScheme
  • getSearchDate
  • getSearchURL
  • getSearchWords
  • getSelectedLayout
  • getSerializedArray
  • getSetClause
  • getSiteHomeURL
  • getSitemapAlbumList
  • getSitemapAlbums
  • getSitemapGoogleImageVideoExtras
  • getSitemapGoogleLoopIndex
  • getSitemapImages
  • getSitemapIndexLinks
  • getSitemapZenpageNewsArticles
  • getSitemapZenpageNewsCategories
  • getSitemapZenpageNewsIndex
  • getSitemapZenpagePages
  • getSizeCustomImage
  • getSizeDefaultImage
  • getSizeDefaultThumb
  • getSizedImageURL
  • getSizeFullImage
  • getStore
  • getSubCategories
  • getSubtabs
  • getSuffix
  • getTagCountByAccess
  • getTagOrder
  • getTags
  • gettext_pl
  • gettext_th
  • getTheme
  • getThemeFiles
  • getThemeOption
  • getTimezones
  • getTinyMCE4ConfigFiles
  • getTitle
  • getTotalArticles
  • getTotalImagesIn
  • getTotalNewsPages
  • getTotalPages
  • getTrustRoot
  • getUnprotectedImageURL
  • getUrAlbum
  • getURL
  • getUserIP
  • getUserLocale
  • getVersion
  • getViewerImageSize
  • getWatermarkParam
  • getWatermarkPath
  • getWatermarks
  • getWhereClause
  • getXSRFToken
  • getZenpageHitcounter
  • getZenpageRSSHeaderLink
  • getZenpageRSSLink
  • getZenpageStatistic
  • googleVerifyHead
  • handleSearchParms
  • hasDynamicAlbumSuffix
  • hasNextImage
  • hasNextPage
  • hasPrevImage
  • hasPrevPage
  • hitcounter
  • html_decode
  • html_encode
  • html_encodeTagged
  • httpsRedirect
  • httpUploadHandler
  • httpUploadHandler_admin_tabs
  • i18nSetLocale
  • imageBlurGD
  • imageDebug
  • imageError
  • imageNumber
  • imgSrcURI
  • in_context
  • inNewsCategory
  • inProtectedNewsCategory
  • installSignature
  • instrument
  • inSubNewsCategoryOf
  • internalToFilesystem
  • inventMenuItem
  • iptc_make_tag
  • is_AdminEditPage
  • is_connected
  • is_GalleryNewsType
  • is_News
  • is_NewsArchive
  • is_NewsArticle
  • is_NewsCategory
  • is_NewsPage
  • is_NewsType
  • is_Pages
  • is_valid_email_zp
  • is_valid_image
  • is_valid_other_type
  • is_zip
  • isAlbumClass
  • isAlbumPage
  • isArchive
  • isHandledAlbum
  • isImageClass
  • isImagePage
  • isImagePhoto
  • isImageVideo
  • isLandscape
  • isMyAlbum
  • isMyNews
  • isMyPage
  • isolate
  • isProtectedAlbum
  • isProtectedNewsCategory
  • isProtectedPage
  • isSubNewsCategoryOf
  • isValidURL
  • jQueryUpload_head
  • jQueryUpload_headers
  • jQueryUploadHandler
  • jQueryUploadHandler_admin_tabs
  • js_encode
  • json_decode
  • json_encode
  • kses
  • kses_array_lc
  • kses_attr
  • kses_bad_protocol
  • kses_bad_protocol_once
  • kses_bad_protocol_once2
  • kses_check_attr_val
  • kses_decode_entities
  • kses_hair
  • kses_hook
  • kses_html_error
  • kses_js_entities
  • kses_no_null
  • kses_normalize_entities
  • kses_normalize_entities2
  • kses_split
  • kses_split2
  • kses_stripslashes
  • kses_version
  • ksesProcess
  • layoutSelector
  • layoutSelector_album
  • listDBUses
  • listDirectoryFiles
  • listUses
  • load_zenpage_news
  • load_zenpage_pages
  • loadLocalOptions
  • log_message
  • lookupSortKey
  • macro_admin_tabs
  • macroList_show
  • makeAlbumCurrent
  • makeImageCurrent
  • makeSpecialImageName
  • markRelease_button
  • mb_strlen
  • mb_strpos
  • mb_strrpos
  • mb_strtolower
  • mb_strtoupper
  • mb_substr
  • mb_substr_count
  • menu_admin_toolbox_global
  • menu_tabs
  • minDiff
  • mkdir_recursive
  • my_truncate_string
  • myts_date
  • newAlbum
  • newImage
  • next_album
  • next_comment
  • next_image
  • next_news
  • next_page
  • ngettext_pl
  • ngettext_th
  • normalizeColumns
  • omsAdditions
  • openedForComments
  • parse_query
  • parse_size
  • parseAllowedTags
  • parseHttpAcceptLanguage
  • passAlbums
  • passImages
  • pathurlencode
  • PclZipUtilCopyBlock
  • PclZipUtilOptionText
  • PclZipUtilPathInclusion
  • PclZipUtilPathReduction
  • PclZipUtilRename
  • PclZipUtilTranslateWinPath
  • PHPMailerAutoload
  • populateManagedObjectsList
  • postAlbumSort
  • postIndexDecode
  • postIndexEncode
  • prefix
  • prepareAlbumPage
  • prepareCustomPage
  • prepareImagePage
  • prepareIndexPage
  • print404status
  • print_language_string_list
  • printAddToFavorites
  • printAdminFooter
  • printAdminHeader
  • printAdminRightsTable
  • printAdminToolbox
  • printAlbumBreadcrumb
  • printAlbumButtons
  • printAlbumCustomData
  • printAlbumData
  • printAlbumDate
  • printAlbumDesc
  • printAlbumEditForm
  • printAlbumEditRow
  • printAlbumLegend
  • printAlbumLink
  • printAlbumLocation
  • printAlbumMap
  • printAlbumMenu
  • printAlbumMenuJump
  • printAlbumMenuList
  • printAlbumMenuListAlbum
  • printAlbumPlace
  • printAlbumRating
  • printAlbumsSelector
  • printAlbumStatistic
  • printAlbumStatisticItem
  • printAlbumThumbImage
  • printAlbumTitle
  • printAlbumURL
  • printAlbumZip
  • printAllDates
  • printAllNewsCategories
  • printAllTags
  • printAllTagsAs
  • printAllTagsFromAlbum
  • printAllTagsFromZenpage
  • printAnnotatedAlbumTitle
  • printAnnotatedImageTitle
  • printArticleCategories
  • printArticleDatesDropdown
  • printArticlesPerPageDropdown
  • printBareAlbumDesc
  • printBareAlbumTitle
  • printBareGalleryDesc
  • printBareGalleryTitle
  • printBareImageDesc
  • printBareImageTitle
  • printBareNewsTitle
  • printBarePageTitle
  • printBulkActions
  • printCaptcha
  • printCategoriesStatistic
  • printCategoryCheckboxListEntry
  • printCategoryDropdown
  • printCategoryListSortableTable
  • printCategorySelection
  • printCodeblock
  • printCodeblockEdit
  • printCommentAuthorLink
  • printCommentErrors
  • printCommentForm
  • printContactForm
  • printCurrentNewsArchive
  • printCurrentNewsCategory
  • printCustomAlbumThumbImage
  • printCustomAlbumThumbMaxSpace
  • printCustomMenu
  • printCustomPageSelector
  • printCustomPageURL
  • printCustomSizedImage
  • printCustomSizedImageMaxHeight
  • printCustomSizedImageMaxSpace
  • printCustomSizedImageThumbMaxSpace
  • printDefaultSizedImage
  • printDownloadAlbumZipURL
  • printDownloadLink
  • printDownloadLinkAlbumZip
  • printdownloadList
  • printDownloadURL
  • printEditable
  • printEditCommentLink
  • printEditDropdown
  • printExpired
  • printFavoritesLink
  • printFavoritesURL
  • printField
  • printGalleryDesc
  • printGalleryIndexURL
  • printGalleryTitle
  • printGoogleMap
  • printHeadTitle
  • printHomeLink
  • printImageCustomData
  • printImageData
  • printImageDate
  • printImageDesc
  • printImageDiv
  • printImageEXIFData
  • printImageID
  • printImageLink
  • printImageMap
  • printImageMetadata
  • printImageRating
  • printImageSortOrder
  • printImageStatistic
  • printImageThumb
  • printImageTitle
  • printImageURL
  • printItemEditLink
  • printItemsList
  • printItemsListTable
  • printItemStatusDropdown
  • printjCarouselThumbNav
  • printjPlayerPlaylist
  • printLanguageSelector
  • printLatestAlbums
  • printLatestComments
  • printLatestImages
  • printLatestImagesByDate
  • printLatestImagesByMtime
  • printLatestNews
  • printLatestUpdatedAlbums
  • printLatestZenpageComments
  • printLink
  • printLinkHTML
  • printLogoAndLinks
  • printManagedObjects
  • printMenuemanagerPageList
  • printMenuemanagerPageListWithNav
  • printMenumanagerBreadcrumb
  • printMenumanagerNextLink
  • printMenumanagerPrevLink
  • printMostPopularItems
  • printMostRatedAlbums
  • printMostRatedImages
  • printMostRatedItems
  • printNestedAlbumsList
  • printNestedItemsList
  • printNestedMenu
  • printNews
  • printNewsArchive
  • printNewsAuthor
  • printNewsCategories
  • printNewsCategoryCustomData
  • printNewsCategoryDesc
  • printNewsCategoryURL
  • printNewsContent
  • printNewsCustomData
  • printNewsDate
  • printNewsExtraContent
  • printNewsImageTags
  • printNewsIndexURL
  • printNewsLink
  • printNewsPageList
  • printNewsPageListWithNav
  • printNewsReadMoreLink
  • printNewsStatistic
  • printNewsTitle
  • printNewsTitleLink
  • printNewsURL
  • printNextNewsLink
  • printNextNewsPageLink
  • printNextPageLink
  • printNextPageURL
  • printPageArticleTags
  • printPageAuthor
  • printPageContent
  • printPageCustomData
  • printPageDate
  • printPagedThumbsNav
  • printPageExtraContent
  • printPageID
  • printPageLastChangeDate
  • printPageLinkURL
  • printPageList
  • printPageListWithNav
  • printPageMenu
  • printPageNav
  • printPageSelector
  • printPagesListTable
  • printPagesStatistic
  • printPageTitle
  • printPageTitleLink
  • printPageURL
  • printParentBreadcrumb
  • printParentPagesBreadcrumb
  • printPasswordForm
  • printPopularAlbums
  • printPopularImages
  • printPreloadScript
  • printPrevNewsLink
  • printPrevNewsPageLink
  • printPrevPageLink
  • printPrevPageURL
  • printPublished
  • printPublishIconLink
  • printRandomImages
  • printRating
  • printRegisterURL
  • printRegistrationForm
  • printRelatedItems
  • printRSSHeaderLink
  • printRSSLink
  • printSearchBreadcrumb
  • printSearchForm
  • printSiteHomeURL
  • printSizedImageLink
  • printSizedImageURL
  • printSlideShow
  • printSlideShowJS
  • printSlideShowLink
  • printSortableHead
  • printSortOrderDropdown
  • printSubPagesExcerpts
  • printSubtabs
  • printTabs
  • printTags
  • printThumbNav
  • printTopRatedAlbums
  • printTopRatedImages
  • printTopRatedItems
  • printUnpublishedDropdown
  • printUserLogin_out
  • printUserSizeImage
  • printUserSizeSelector
  • printVersion
  • printZenJavascripts
  • printZenpageIconLegend
  • printZenpageItemsBreadcrumb
  • printZenpageNewsCategorySelector
  • printZenpagePagesSelector
  • printZenpageRSSHeaderLink
  • printZenpageRSSLink
  • printZenpageStatistic
  • printZenphotoLink
  • process_language_string_save
  • processAlbumBulkActions
  • processAlbumEdit
  • processCodeblockSave
  • processCommentBulkActions
  • processCredentials
  • processCustomOptionSave
  • processEditSelection
  • processExpired
  • processImageBulkActions
  • processImageEdit
  • processManagedObjects
  • processMenuBulkActions
  • processOrder
  • processRights
  • processTags
  • processZenpageBulkActions
  • propSizes
  • publishItem
  • purgeOption
  • query
  • query_full_array
  • query_single_row
  • rc4
  • read_exif_data_protected
  • readTags
  • recaptcha_check_answer
  • recaptcha_get_html
  • recaptcha_get_signup_url
  • recaptcha_mailhide_html
  • recaptcha_mailhide_url
  • reconfigureAction
  • reconfigureCS
  • reconfigurePage
  • recordMissing
  • rem_context
  • removeParentAlbumNames
  • resetCurrentAlbum
  • restore_context
  • reveal
  • rewrite_get_album_image
  • rewrite_path
  • rewrite_path_zenpage
  • RSS_Channel
  • RSS_Retrieve
  • RSS_Tags
  • rulesList
  • run
  • safe_fnmatch
  • safe_glob
  • sanitize
  • sanitize_numeric
  • sanitize_path
  • sanitize_script
  • sanitize_string
  • sanitizeRedirect
  • save_context
  • saveLayoutSelection
  • saveZenphotoLayoutSelection
  • search_quote
  • secureServer
  • seo_cleanup_button
  • seoFriendly
  • seoFriendlyJS
  • set_context
  • setAlbumCustomData
  • setAlbumSubtabs
  • setImageCustomData
  • setMainDomain
  • setOption
  • setOptionDefault
  • setPluginDomain
  • setThemeColumns
  • setThemeDomain
  • setThemeOption
  • setThemeOptionDefault
  • setupAllowedMaps
  • setupCurrentLocale
  • setupDomain
  • setupTheme
  • shortenContent
  • showOrNotShowField
  • shuffle_assoc
  • signatureChange
  • site_upgrade_button
  • site_upgrade_status
  • sitemap_echonl
  • sitemap_getChangefreq
  • sitemap_getDateformat
  • sitemap_getDBLimit
  • sitemap_getISO8601Date
  • skipScheduledPublishing
  • sortByKey
  • sortByMultilingual
  • sortMultiArray
  • standardScripts
  • standardThemeOptions
  • stickyNews
  • storeConfig
  • storeTags
  • stripSuffix
  • submenuOf
  • switchLog
  • tagSelector
  • tagSuggestJS
  • tagSuggestJS_admin
  • tagSuggestJS_frontend
  • themeIsEditable
  • themeSetup
  • timezoneDiff
  • tinymce4ConfigJS
  • truncate_string
  • unpublishedZenphotoItemCheck
  • unpublishSubalbums
  • unQuote
  • unzip
  • updateArticle
  • updateCacheName
  • updateCategory
  • updateConfigItem
  • updateItemSortorder
  • updateItemsSortorder
  • updateMenuItem
  • updatePage
  • upload_extra
  • upload_form
  • upload_head
  • user_mailing_list_button
  • validateLocale
  • wordpress_import_button
  • wp_prefix
  • wp_query_full_array
  • wpimport_TryAgainError
  • XSRFdefender
  • XSRFToken
  • zenJavascript
  • zenpageAlbumImage
  • zenpageBulkActionMessage
  • zenpageHitcounter
  • zenpageJSCSS
  • zenpageOpenedForComments
  • zenpagePublish
  • zenphoto_PHPMailer
  • zenphoto_sendmail
  • zenPhotoTheme
  • zp_apply_filter
  • zp_clearCookie
  • zp_colorAllocate
  • zp_cookieEncode
  • zp_copyCanvas
  • zp_createImage
  • zp_drawRectangle
  • zp_error
  • zp_filter_slot
  • zp_filter_unique_id
  • zp_getCookie
  • zp_getFonts
  • zp_graphicsLibInfo
  • zp_handle_password
  • zp_handle_password_single
  • zp_has_filter
  • zp_image_types
  • zp_imageCanRotate
  • zp_imageColorTransparent
  • zp_imageDims
  • zp_imageFill
  • zp_imageFontHeight
  • zp_imageFontWidth
  • zp_imageFromString
  • zp_imageGet
  • zp_imageGray
  • zp_imageHeight
  • zp_imageIPTC
  • zp_imageKill
  • zp_imageLoadFont
  • zp_imageMerge
  • zp_imageOutput
  • zp_imageResizeAlpha
  • zp_imageUnsharpMask
  • zp_imageWidth
  • zp_load_album
  • zp_load_gallery
  • zp_load_image
  • zp_load_page
  • zp_load_request
  • zp_load_search
  • zp_loggedin
  • zp_mail
  • zp_register_filter
  • zp_remove_filter
  • zp_resampleImage
  • zp_rotateImage
  • zp_session_start
  • zp_setCookie
  • zp_writeString
  • zpErrorHandler
  • zpFormattedDate
  • zpRewriteURL
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
   1: <?php
   2: /**
   3:  * PHPMailer - PHP email creation and 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 2012 - 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 - PHP email creation and transport class.
  22:  * @package PHPMailer
  23:  * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
  24:  * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
  25:  * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  26:  * @author Brent R. Matzelle (original founder)
  27:  */
  28: class PHPMailer
  29: {
  30:     /**
  31:      * The PHPMailer Version number.
  32:      * @var string
  33:      */
  34:     public $Version = '5.2.22';
  35: 
  36:     /**
  37:      * Email priority.
  38:      * Options: null (default), 1 = High, 3 = Normal, 5 = low.
  39:      * When null, the header is not set at all.
  40:      * @var integer
  41:      */
  42:     public $Priority = null;
  43: 
  44:     /**
  45:      * The character set of the message.
  46:      * @var string
  47:      */
  48:     public $CharSet = 'iso-8859-1';
  49: 
  50:     /**
  51:      * The MIME Content-type of the message.
  52:      * @var string
  53:      */
  54:     public $ContentType = 'text/plain';
  55: 
  56:     /**
  57:      * The message encoding.
  58:      * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable".
  59:      * @var string
  60:      */
  61:     public $Encoding = '8bit';
  62: 
  63:     /**
  64:      * Holds the most recent mailer error message.
  65:      * @var string
  66:      */
  67:     public $ErrorInfo = '';
  68: 
  69:     /**
  70:      * The From email address for the message.
  71:      * @var string
  72:      */
  73:     public $From = 'root@localhost';
  74: 
  75:     /**
  76:      * The From name of the message.
  77:      * @var string
  78:      */
  79:     public $FromName = 'Root User';
  80: 
  81:     /**
  82:      * The Sender email (Return-Path) of the message.
  83:      * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
  84:      * @var string
  85:      */
  86:     public $Sender = '';
  87: 
  88:     /**
  89:      * The Return-Path of the message.
  90:      * If empty, it will be set to either From or Sender.
  91:      * @var string
  92:      * @deprecated Email senders should never set a return-path header;
  93:      * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything.
  94:      * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference
  95:      */
  96:     public $ReturnPath = '';
  97: 
  98:     /**
  99:      * The Subject of the message.
 100:      * @var string
 101:      */
 102:     public $Subject = '';
 103: 
 104:     /**
 105:      * An HTML or plain text message body.
 106:      * If HTML then call isHTML(true).
 107:      * @var string
 108:      */
 109:     public $Body = '';
 110: 
 111:     /**
 112:      * The plain-text message body.
 113:      * This body can be read by mail clients that do not have HTML email
 114:      * capability such as mutt & Eudora.
 115:      * Clients that can read HTML will view the normal Body.
 116:      * @var string
 117:      */
 118:     public $AltBody = '';
 119: 
 120:     /**
 121:      * An iCal message part body.
 122:      * Only supported in simple alt or alt_inline message types
 123:      * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator
 124:      * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/
 125:      * @link http://kigkonsult.se/iCalcreator/
 126:      * @var string
 127:      */
 128:     public $Ical = '';
 129: 
 130:     /**
 131:      * The complete compiled MIME message body.
 132:      * @access protected
 133:      * @var string
 134:      */
 135:     protected $MIMEBody = '';
 136: 
 137:     /**
 138:      * The complete compiled MIME message headers.
 139:      * @var string
 140:      * @access protected
 141:      */
 142:     protected $MIMEHeader = '';
 143: 
 144:     /**
 145:      * Extra headers that createHeader() doesn't fold in.
 146:      * @var string
 147:      * @access protected
 148:      */
 149:     protected $mailHeader = '';
 150: 
 151:     /**
 152:      * Word-wrap the message body to this number of chars.
 153:      * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance.
 154:      * @var integer
 155:      */
 156:     public $WordWrap = 0;
 157: 
 158:     /**
 159:      * Which method to use to send mail.
 160:      * Options: "mail", "sendmail", or "smtp".
 161:      * @var string
 162:      */
 163:     public $Mailer = 'mail';
 164: 
 165:     /**
 166:      * The path to the sendmail program.
 167:      * @var string
 168:      */
 169:     public $Sendmail = '/usr/sbin/sendmail';
 170: 
 171:     /**
 172:      * Whether mail() uses a fully sendmail-compatible MTA.
 173:      * One which supports sendmail's "-oi -f" options.
 174:      * @var boolean
 175:      */
 176:     public $UseSendmailOptions = true;
 177: 
 178:     /**
 179:      * Path to PHPMailer plugins.
 180:      * Useful if the SMTP class is not in the PHP include path.
 181:      * @var string
 182:      * @deprecated Should not be needed now there is an autoloader.
 183:      */
 184:     public $PluginDir = '';
 185: 
 186:     /**
 187:      * The email address that a reading confirmation should be sent to, also known as read receipt.
 188:      * @var string
 189:      */
 190:     public $ConfirmReadingTo = '';
 191: 
 192:     /**
 193:      * The hostname to use in the Message-ID header and as default HELO string.
 194:      * If empty, PHPMailer attempts to find one with, in order,
 195:      * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value
 196:      * 'localhost.localdomain'.
 197:      * @var string
 198:      */
 199:     public $Hostname = '';
 200: 
 201:     /**
 202:      * An ID to be used in the Message-ID header.
 203:      * If empty, a unique id will be generated.
 204:      * You can set your own, but it must be in the format "<id@domain>",
 205:      * as defined in RFC5322 section 3.6.4 or it will be ignored.
 206:      * @see https://tools.ietf.org/html/rfc5322#section-3.6.4
 207:      * @var string
 208:      */
 209:     public $MessageID = '';
 210: 
 211:     /**
 212:      * The message Date to be used in the Date header.
 213:      * If empty, the current date will be added.
 214:      * @var string
 215:      */
 216:     public $MessageDate = '';
 217: 
 218:     /**
 219:      * SMTP hosts.
 220:      * Either a single hostname or multiple semicolon-delimited hostnames.
 221:      * You can also specify a different port
 222:      * for each host by using this format: [hostname:port]
 223:      * (e.g. "smtp1.example.com:25;smtp2.example.com").
 224:      * You can also specify encryption type, for example:
 225:      * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
 226:      * Hosts will be tried in order.
 227:      * @var string
 228:      */
 229:     public $Host = 'localhost';
 230: 
 231:     /**
 232:      * The default SMTP server port.
 233:      * @var integer
 234:      * @TODO Why is this needed when the SMTP class takes care of it?
 235:      */
 236:     public $Port = 25;
 237: 
 238:     /**
 239:      * The SMTP HELO of the message.
 240:      * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find
 241:      * one with the same method described above for $Hostname.
 242:      * @var string
 243:      * @see PHPMailer::$Hostname
 244:      */
 245:     public $Helo = '';
 246: 
 247:     /**
 248:      * What kind of encryption to use on the SMTP connection.
 249:      * Options: '', 'ssl' or 'tls'
 250:      * @var string
 251:      */
 252:     public $SMTPSecure = '';
 253: 
 254:     /**
 255:      * Whether to enable TLS encryption automatically if a server supports it,
 256:      * even if `SMTPSecure` is not set to 'tls'.
 257:      * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid.
 258:      * @var boolean
 259:      */
 260:     public $SMTPAutoTLS = true;
 261: 
 262:     /**
 263:      * Whether to use SMTP authentication.
 264:      * Uses the Username and Password properties.
 265:      * @var boolean
 266:      * @see PHPMailer::$Username
 267:      * @see PHPMailer::$Password
 268:      */
 269:     public $SMTPAuth = false;
 270: 
 271:     /**
 272:      * Options array passed to stream_context_create when connecting via SMTP.
 273:      * @var array
 274:      */
 275:     public $SMTPOptions = array();
 276: 
 277:     /**
 278:      * SMTP username.
 279:      * @var string
 280:      */
 281:     public $Username = '';
 282: 
 283:     /**
 284:      * SMTP password.
 285:      * @var string
 286:      */
 287:     public $Password = '';
 288: 
 289:     /**
 290:      * SMTP auth type.
 291:      * Options are CRAM-MD5, LOGIN, PLAIN, NTLM, XOAUTH2, attempted in that order if not specified
 292:      * @var string
 293:      */
 294:     public $AuthType = '';
 295: 
 296:     /**
 297:      * SMTP realm.
 298:      * Used for NTLM auth
 299:      * @var string
 300:      */
 301:     public $Realm = '';
 302: 
 303:     /**
 304:      * SMTP workstation.
 305:      * Used for NTLM auth
 306:      * @var string
 307:      */
 308:     public $Workstation = '';
 309: 
 310:     /**
 311:      * The SMTP server timeout in seconds.
 312:      * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
 313:      * @var integer
 314:      */
 315:     public $Timeout = 300;
 316: 
 317:     /**
 318:      * SMTP class debug output mode.
 319:      * Debug output level.
 320:      * Options:
 321:      * * `0` No output
 322:      * * `1` Commands
 323:      * * `2` Data and commands
 324:      * * `3` As 2 plus connection status
 325:      * * `4` Low-level data output
 326:      * @var integer
 327:      * @see SMTP::$do_debug
 328:      */
 329:     public $SMTPDebug = 0;
 330: 
 331:     /**
 332:      * How to handle debug output.
 333:      * Options:
 334:      * * `echo` Output plain-text as-is, appropriate for CLI
 335:      * * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
 336:      * * `error_log` Output to error log as configured in php.ini
 337:      *
 338:      * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
 339:      * <code>
 340:      * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
 341:      * </code>
 342:      * @var string|callable
 343:      * @see SMTP::$Debugoutput
 344:      */
 345:     public $Debugoutput = 'echo';
 346: 
 347:     /**
 348:      * Whether to keep SMTP connection open after each message.
 349:      * If this is set to true then to close the connection
 350:      * requires an explicit call to smtpClose().
 351:      * @var boolean
 352:      */
 353:     public $SMTPKeepAlive = false;
 354: 
 355:     /**
 356:      * Whether to split multiple to addresses into multiple messages
 357:      * or send them all in one message.
 358:      * Only supported in `mail` and `sendmail` transports, not in SMTP.
 359:      * @var boolean
 360:      */
 361:     public $SingleTo = false;
 362: 
 363:     /**
 364:      * Storage for addresses when SingleTo is enabled.
 365:      * @var array
 366:      * @TODO This should really not be public
 367:      */
 368:     public $SingleToArray = array();
 369: 
 370:     /**
 371:      * Whether to generate VERP addresses on send.
 372:      * Only applicable when sending via SMTP.
 373:      * @link https://en.wikipedia.org/wiki/Variable_envelope_return_path
 374:      * @link http://www.postfix.org/VERP_README.html Postfix VERP info
 375:      * @var boolean
 376:      */
 377:     public $do_verp = false;
 378: 
 379:     /**
 380:      * Whether to allow sending messages with an empty body.
 381:      * @var boolean
 382:      */
 383:     public $AllowEmpty = false;
 384: 
 385:     /**
 386:      * The default line ending.
 387:      * @note The default remains "\n". We force CRLF where we know
 388:      *        it must be used via self::CRLF.
 389:      * @var string
 390:      */
 391:     public $LE = "\n";
 392: 
 393:     /**
 394:      * DKIM selector.
 395:      * @var string
 396:      */
 397:     public $DKIM_selector = '';
 398: 
 399:     /**
 400:      * DKIM Identity.
 401:      * Usually the email address used as the source of the email.
 402:      * @var string
 403:      */
 404:     public $DKIM_identity = '';
 405: 
 406:     /**
 407:      * DKIM passphrase.
 408:      * Used if your key is encrypted.
 409:      * @var string
 410:      */
 411:     public $DKIM_passphrase = '';
 412: 
 413:     /**
 414:      * DKIM signing domain name.
 415:      * @example 'example.com'
 416:      * @var string
 417:      */
 418:     public $DKIM_domain = '';
 419: 
 420:     /**
 421:      * DKIM private key file path.
 422:      * @var string
 423:      */
 424:     public $DKIM_private = '';
 425: 
 426:     /**
 427:      * DKIM private key string.
 428:      * If set, takes precedence over `$DKIM_private`.
 429:      * @var string
 430:      */
 431:     public $DKIM_private_string = '';
 432: 
 433:     /**
 434:      * Callback Action function name.
 435:      *
 436:      * The function that handles the result of the send email action.
 437:      * It is called out by send() for each email sent.
 438:      *
 439:      * Value can be any php callable: http://www.php.net/is_callable
 440:      *
 441:      * Parameters:
 442:      *   boolean $result        result of the send action
 443:      *   string  $to            email address of the recipient
 444:      *   string  $cc            cc email addresses
 445:      *   string  $bcc           bcc email addresses
 446:      *   string  $subject       the subject
 447:      *   string  $body          the email body
 448:      *   string  $from          email address of sender
 449:      * @var string
 450:      */
 451:     public $action_function = '';
 452: 
 453:     /**
 454:      * What to put in the X-Mailer header.
 455:      * Options: An empty string for PHPMailer default, whitespace for none, or a string to use
 456:      * @var string
 457:      */
 458:     public $XMailer = '';
 459: 
 460:     /**
 461:      * Which validator to use by default when validating email addresses.
 462:      * May be a callable to inject your own validator, but there are several built-in validators.
 463:      * @see PHPMailer::validateAddress()
 464:      * @var string|callable
 465:      * @static
 466:      */
 467:     public static $validator = 'auto';
 468: 
 469:     /**
 470:      * An instance of the SMTP sender class.
 471:      * @var SMTP
 472:      * @access protected
 473:      */
 474:     protected $smtp = null;
 475: 
 476:     /**
 477:      * The array of 'to' names and addresses.
 478:      * @var array
 479:      * @access protected
 480:      */
 481:     protected $to = array();
 482: 
 483:     /**
 484:      * The array of 'cc' names and addresses.
 485:      * @var array
 486:      * @access protected
 487:      */
 488:     protected $cc = array();
 489: 
 490:     /**
 491:      * The array of 'bcc' names and addresses.
 492:      * @var array
 493:      * @access protected
 494:      */
 495:     protected $bcc = array();
 496: 
 497:     /**
 498:      * The array of reply-to names and addresses.
 499:      * @var array
 500:      * @access protected
 501:      */
 502:     protected $ReplyTo = array();
 503: 
 504:     /**
 505:      * An array of all kinds of addresses.
 506:      * Includes all of $to, $cc, $bcc
 507:      * @var array
 508:      * @access protected
 509:      * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc
 510:      */
 511:     protected $all_recipients = array();
 512: 
 513:     /**
 514:      * An array of names and addresses queued for validation.
 515:      * In send(), valid and non duplicate entries are moved to $all_recipients
 516:      * and one of $to, $cc, or $bcc.
 517:      * This array is used only for addresses with IDN.
 518:      * @var array
 519:      * @access protected
 520:      * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc
 521:      * @see PHPMailer::$all_recipients
 522:      */
 523:     protected $RecipientsQueue = array();
 524: 
 525:     /**
 526:      * An array of reply-to names and addresses queued for validation.
 527:      * In send(), valid and non duplicate entries are moved to $ReplyTo.
 528:      * This array is used only for addresses with IDN.
 529:      * @var array
 530:      * @access protected
 531:      * @see PHPMailer::$ReplyTo
 532:      */
 533:     protected $ReplyToQueue = array();
 534: 
 535:     /**
 536:      * The array of attachments.
 537:      * @var array
 538:      * @access protected
 539:      */
 540:     protected $attachment = array();
 541: 
 542:     /**
 543:      * The array of custom headers.
 544:      * @var array
 545:      * @access protected
 546:      */
 547:     protected $CustomHeader = array();
 548: 
 549:     /**
 550:      * The most recent Message-ID (including angular brackets).
 551:      * @var string
 552:      * @access protected
 553:      */
 554:     protected $lastMessageID = '';
 555: 
 556:     /**
 557:      * The message's MIME type.
 558:      * @var string
 559:      * @access protected
 560:      */
 561:     protected $message_type = '';
 562: 
 563:     /**
 564:      * The array of MIME boundary strings.
 565:      * @var array
 566:      * @access protected
 567:      */
 568:     protected $boundary = array();
 569: 
 570:     /**
 571:      * The array of available languages.
 572:      * @var array
 573:      * @access protected
 574:      */
 575:     protected $language = array();
 576: 
 577:     /**
 578:      * The number of errors encountered.
 579:      * @var integer
 580:      * @access protected
 581:      */
 582:     protected $error_count = 0;
 583: 
 584:     /**
 585:      * The S/MIME certificate file path.
 586:      * @var string
 587:      * @access protected
 588:      */
 589:     protected $sign_cert_file = '';
 590: 
 591:     /**
 592:      * The S/MIME key file path.
 593:      * @var string
 594:      * @access protected
 595:      */
 596:     protected $sign_key_file = '';
 597: 
 598:     /**
 599:      * The optional S/MIME extra certificates ("CA Chain") file path.
 600:      * @var string
 601:      * @access protected
 602:      */
 603:     protected $sign_extracerts_file = '';
 604: 
 605:     /**
 606:      * The S/MIME password for the key.
 607:      * Used only if the key is encrypted.
 608:      * @var string
 609:      * @access protected
 610:      */
 611:     protected $sign_key_pass = '';
 612: 
 613:     /**
 614:      * Whether to throw exceptions for errors.
 615:      * @var boolean
 616:      * @access protected
 617:      */
 618:     protected $exceptions = false;
 619: 
 620:     /**
 621:      * Unique ID used for message ID and boundaries.
 622:      * @var string
 623:      * @access protected
 624:      */
 625:     protected $uniqueid = '';
 626: 
 627:     /**
 628:      * Error severity: message only, continue processing.
 629:      */
 630:     const STOP_MESSAGE = 0;
 631: 
 632:     /**
 633:      * Error severity: message, likely ok to continue processing.
 634:      */
 635:     const STOP_CONTINUE = 1;
 636: 
 637:     /**
 638:      * Error severity: message, plus full stop, critical error reached.
 639:      */
 640:     const STOP_CRITICAL = 2;
 641: 
 642:     /**
 643:      * SMTP RFC standard line ending.
 644:      */
 645:     const CRLF = "\r\n";
 646: 
 647:     /**
 648:      * The maximum line length allowed by RFC 2822 section 2.1.1
 649:      * @var integer
 650:      */
 651:     const MAX_LINE_LENGTH = 998;
 652: 
 653:     /**
 654:      * Constructor.
 655:      * @param boolean $exceptions Should we throw external exceptions?
 656:      */
 657:     public function __construct($exceptions = null)
 658:     {
 659:         if ($exceptions !== null) {
 660:             $this->exceptions = (boolean)$exceptions;
 661:         }
 662:     }
 663: 
 664:     /**
 665:      * Destructor.
 666:      */
 667:     public function __destruct()
 668:     {
 669:         //Close any open SMTP connection nicely
 670:         $this->smtpClose();
 671:     }
 672: 
 673:     /**
 674:      * Call mail() in a safe_mode-aware fashion.
 675:      * Also, unless sendmail_path points to sendmail (or something that
 676:      * claims to be sendmail), don't pass params (not a perfect fix,
 677:      * but it will do)
 678:      * @param string $to To
 679:      * @param string $subject Subject
 680:      * @param string $body Message Body
 681:      * @param string $header Additional Header(s)
 682:      * @param string $params Params
 683:      * @access private
 684:      * @return boolean
 685:      */
 686:     private function mailPassthru($to, $subject, $body, $header, $params)
 687:     {
 688:         //Check overloading of mail function to avoid double-encoding
 689:         if (ini_get('mbstring.func_overload') & 1) {
 690:             $subject = $this->secureHeader($subject);
 691:         } else {
 692:             $subject = $this->encodeHeader($this->secureHeader($subject));
 693:         }
 694: 
 695:         //Can't use additional_parameters in safe_mode, calling mail() with null params breaks
 696:         //@link http://php.net/manual/en/function.mail.php
 697:         if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
 698:             $result = @mail($to, $subject, $body, $header);
 699:         } else {
 700:             $result = @mail($to, $subject, $body, $header, $params);
 701:         }
 702:         return $result;
 703:     }
 704:     /**
 705:      * Output debugging info via user-defined method.
 706:      * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
 707:      * @see PHPMailer::$Debugoutput
 708:      * @see PHPMailer::$SMTPDebug
 709:      * @param string $str
 710:      */
 711:     protected function edebug($str)
 712:     {
 713:         if ($this->SMTPDebug <= 0) {
 714:             return;
 715:         }
 716:         //Avoid clash with built-in function names
 717:         if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
 718:             call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
 719:             return;
 720:         }
 721:         switch ($this->Debugoutput) {
 722:             case 'error_log':
 723:                 //Don't output, just log
 724:                 error_log($str);
 725:                 break;
 726:             case 'html':
 727:                 //Cleans up output a bit for a better looking, HTML-safe output
 728:                 echo htmlentities(
 729:                     preg_replace('/[\r\n]+/', '', $str),
 730:                     ENT_QUOTES,
 731:                     'UTF-8'
 732:                 )
 733:                 . "<br>\n";
 734:                 break;
 735:             case 'echo':
 736:             default:
 737:                 //Normalize line breaks
 738:                 $str = preg_replace('/\r\n?/ms', "\n", $str);
 739:                 echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
 740:                     "\n",
 741:                     "\n                   \t                  ",
 742:                     trim($str)
 743:                 ) . "\n";
 744:         }
 745:     }
 746: 
 747:     /**
 748:      * Sets message type to HTML or plain.
 749:      * @param boolean $isHtml True for HTML mode.
 750:      * @return void
 751:      */
 752:     public function isHTML($isHtml = true)
 753:     {
 754:         if ($isHtml) {
 755:             $this->ContentType = 'text/html';
 756:         } else {
 757:             $this->ContentType = 'text/plain';
 758:         }
 759:     }
 760: 
 761:     /**
 762:      * Send messages using SMTP.
 763:      * @return void
 764:      */
 765:     public function isSMTP()
 766:     {
 767:         $this->Mailer = 'smtp';
 768:     }
 769: 
 770:     /**
 771:      * Send messages using PHP's mail() function.
 772:      * @return void
 773:      */
 774:     public function isMail()
 775:     {
 776:         $this->Mailer = 'mail';
 777:     }
 778: 
 779:     /**
 780:      * Send messages using $Sendmail.
 781:      * @return void
 782:      */
 783:     public function isSendmail()
 784:     {
 785:         $ini_sendmail_path = ini_get('sendmail_path');
 786: 
 787:         if (!stristr($ini_sendmail_path, 'sendmail')) {
 788:             $this->Sendmail = '/usr/sbin/sendmail';
 789:         } else {
 790:             $this->Sendmail = $ini_sendmail_path;
 791:         }
 792:         $this->Mailer = 'sendmail';
 793:     }
 794: 
 795:     /**
 796:      * Send messages using qmail.
 797:      * @return void
 798:      */
 799:     public function isQmail()
 800:     {
 801:         $ini_sendmail_path = ini_get('sendmail_path');
 802: 
 803:         if (!stristr($ini_sendmail_path, 'qmail')) {
 804:             $this->Sendmail = '/var/qmail/bin/qmail-inject';
 805:         } else {
 806:             $this->Sendmail = $ini_sendmail_path;
 807:         }
 808:         $this->Mailer = 'qmail';
 809:     }
 810: 
 811:     /**
 812:      * Add a "To" address.
 813:      * @param string $address The email address to send to
 814:      * @param string $name
 815:      * @return boolean true on success, false if address already used or invalid in some way
 816:      */
 817:     public function addAddress($address, $name = '')
 818:     {
 819:         return $this->addOrEnqueueAnAddress('to', $address, $name);
 820:     }
 821: 
 822:     /**
 823:      * Add a "CC" address.
 824:      * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
 825:      * @param string $address The email address to send to
 826:      * @param string $name
 827:      * @return boolean true on success, false if address already used or invalid in some way
 828:      */
 829:     public function addCC($address, $name = '')
 830:     {
 831:         return $this->addOrEnqueueAnAddress('cc', $address, $name);
 832:     }
 833: 
 834:     /**
 835:      * Add a "BCC" address.
 836:      * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
 837:      * @param string $address The email address to send to
 838:      * @param string $name
 839:      * @return boolean true on success, false if address already used or invalid in some way
 840:      */
 841:     public function addBCC($address, $name = '')
 842:     {
 843:         return $this->addOrEnqueueAnAddress('bcc', $address, $name);
 844:     }
 845: 
 846:     /**
 847:      * Add a "Reply-To" address.
 848:      * @param string $address The email address to reply to
 849:      * @param string $name
 850:      * @return boolean true on success, false if address already used or invalid in some way
 851:      */
 852:     public function addReplyTo($address, $name = '')
 853:     {
 854:         return $this->addOrEnqueueAnAddress('Reply-To', $address, $name);
 855:     }
 856: 
 857:     /**
 858:      * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer
 859:      * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still
 860:      * be modified after calling this function), addition of such addresses is delayed until send().
 861:      * Addresses that have been added already return false, but do not throw exceptions.
 862:      * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
 863:      * @param string $address The email address to send, resp. to reply to
 864:      * @param string $name
 865:      * @throws phpmailerException
 866:      * @return boolean true on success, false if address already used or invalid in some way
 867:      * @access protected
 868:      */
 869:     protected function addOrEnqueueAnAddress($kind, $address, $name)
 870:     {
 871:         $address = trim($address);
 872:         $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
 873:         if (($pos = strrpos($address, '@')) === false) {
 874:             // At-sign is misssing.
 875:             $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
 876:             $this->setError($error_message);
 877:             $this->edebug($error_message);
 878:             if ($this->exceptions) {
 879:                 throw new phpmailerException($error_message);
 880:             }
 881:             return false;
 882:         }
 883:         $params = array($kind, $address, $name);
 884:         // Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
 885:         if ($this->has8bitChars(substr($address, ++$pos)) and $this->idnSupported()) {
 886:             if ($kind != 'Reply-To') {
 887:                 if (!array_key_exists($address, $this->RecipientsQueue)) {
 888:                     $this->RecipientsQueue[$address] = $params;
 889:                     return true;
 890:                 }
 891:             } else {
 892:                 if (!array_key_exists($address, $this->ReplyToQueue)) {
 893:                     $this->ReplyToQueue[$address] = $params;
 894:                     return true;
 895:                 }
 896:             }
 897:             return false;
 898:         }
 899:         // Immediately add standard addresses without IDN.
 900:         return call_user_func_array(array($this, 'addAnAddress'), $params);
 901:     }
 902: 
 903:     /**
 904:      * Add an address to one of the recipient arrays or to the ReplyTo array.
 905:      * Addresses that have been added already return false, but do not throw exceptions.
 906:      * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
 907:      * @param string $address The email address to send, resp. to reply to
 908:      * @param string $name
 909:      * @throws phpmailerException
 910:      * @return boolean true on success, false if address already used or invalid in some way
 911:      * @access protected
 912:      */
 913:     protected function addAnAddress($kind, $address, $name = '')
 914:     {
 915:         if (!in_array($kind, array('to', 'cc', 'bcc', 'Reply-To'))) {
 916:             $error_message = $this->lang('Invalid recipient kind: ') . $kind;
 917:             $this->setError($error_message);
 918:             $this->edebug($error_message);
 919:             if ($this->exceptions) {
 920:                 throw new phpmailerException($error_message);
 921:             }
 922:             return false;
 923:         }
 924:         if (!$this->validateAddress($address)) {
 925:             $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
 926:             $this->setError($error_message);
 927:             $this->edebug($error_message);
 928:             if ($this->exceptions) {
 929:                 throw new phpmailerException($error_message);
 930:             }
 931:             return false;
 932:         }
 933:         if ($kind != 'Reply-To') {
 934:             if (!array_key_exists(strtolower($address), $this->all_recipients)) {
 935:                 array_push($this->$kind, array($address, $name));
 936:                 $this->all_recipients[strtolower($address)] = true;
 937:                 return true;
 938:             }
 939:         } else {
 940:             if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
 941:                 $this->ReplyTo[strtolower($address)] = array($address, $name);
 942:                 return true;
 943:             }
 944:         }
 945:         return false;
 946:     }
 947: 
 948:     /**
 949:      * Parse and validate a string containing one or more RFC822-style comma-separated email addresses
 950:      * of the form "display name <address>" into an array of name/address pairs.
 951:      * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
 952:      * Note that quotes in the name part are removed.
 953:      * @param string $addrstr The address list string
 954:      * @param bool $useimap Whether to use the IMAP extension to parse the list
 955:      * @return array
 956:      * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
 957:      */
 958:     public function parseAddresses($addrstr, $useimap = true)
 959:     {
 960:         $addresses = array();
 961:         if ($useimap and function_exists('imap_rfc822_parse_adrlist')) {
 962:             //Use this built-in parser if it's available
 963:             $list = imap_rfc822_parse_adrlist($addrstr, '');
 964:             foreach ($list as $address) {
 965:                 if ($address->host != '.SYNTAX-ERROR.') {
 966:                     if ($this->validateAddress($address->mailbox . '@' . $address->host)) {
 967:                         $addresses[] = array(
 968:                             'name' => (property_exists($address, 'personal') ? $address->personal : ''),
 969:                             'address' => $address->mailbox . '@' . $address->host
 970:                         );
 971:                     }
 972:                 }
 973:             }
 974:         } else {
 975:             //Use this simpler parser
 976:             $list = explode(',', $addrstr);
 977:             foreach ($list as $address) {
 978:                 $address = trim($address);
 979:                 //Is there a separate name part?
 980:                 if (strpos($address, '<') === false) {
 981:                     //No separate name, just use the whole thing
 982:                     if ($this->validateAddress($address)) {
 983:                         $addresses[] = array(
 984:                             'name' => '',
 985:                             'address' => $address
 986:                         );
 987:                     }
 988:                 } else {
 989:                     list($name, $email) = explode('<', $address);
 990:                     $email = trim(str_replace('>', '', $email));
 991:                     if ($this->validateAddress($email)) {
 992:                         $addresses[] = array(
 993:                             'name' => trim(str_replace(array('"', "'"), '', $name)),
 994:                             'address' => $email
 995:                         );
 996:                     }
 997:                 }
 998:             }
 999:         }
1000:         return $addresses;
1001:     }
1002: 
1003:     /**
1004:      * Set the From and FromName properties.
1005:      * @param string $address
1006:      * @param string $name
1007:      * @param boolean $auto Whether to also set the Sender address, defaults to true
1008:      * @throws phpmailerException
1009:      * @return boolean
1010:      */
1011:     public function setFrom($address, $name = '', $auto = true)
1012:     {
1013:         $address = trim($address);
1014:         $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
1015:         // Don't validate now addresses with IDN. Will be done in send().
1016:         if (($pos = strrpos($address, '@')) === false or
1017:             (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
1018:             !$this->validateAddress($address)) {
1019:             $error_message = $this->lang('invalid_address') . " (setFrom) $address";
1020:             $this->setError($error_message);
1021:             $this->edebug($error_message);
1022:             if ($this->exceptions) {
1023:                 throw new phpmailerException($error_message);
1024:             }
1025:             return false;
1026:         }
1027:         $this->From = $address;
1028:         $this->FromName = $name;
1029:         if ($auto) {
1030:             if (empty($this->Sender)) {
1031:                 $this->Sender = $address;
1032:             }
1033:         }
1034:         return true;
1035:     }
1036: 
1037:     /**
1038:      * Return the Message-ID header of the last email.
1039:      * Technically this is the value from the last time the headers were created,
1040:      * but it's also the message ID of the last sent message except in
1041:      * pathological cases.
1042:      * @return string
1043:      */
1044:     public function getLastMessageID()
1045:     {
1046:         return $this->lastMessageID;
1047:     }
1048: 
1049:     /**
1050:      * Check that a string looks like an email address.
1051:      * @param string $address The email address to check
1052:      * @param string|callable $patternselect A selector for the validation pattern to use :
1053:      * * `auto` Pick best pattern automatically;
1054:      * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
1055:      * * `pcre` Use old PCRE implementation;
1056:      * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
1057:      * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
1058:      * * `noregex` Don't use a regex: super fast, really dumb.
1059:      * Alternatively you may pass in a callable to inject your own validator, for example:
1060:      * PHPMailer::validateAddress('user@example.com', function($address) {
1061:      *     return (strpos($address, '@') !== false);
1062:      * });
1063:      * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
1064:      * @return boolean
1065:      * @static
1066:      * @access public
1067:      */
1068:     public static function validateAddress($address, $patternselect = null)
1069:     {
1070:         if (is_null($patternselect)) {
1071:             $patternselect = self::$validator;
1072:         }
1073:         if (is_callable($patternselect)) {
1074:             return call_user_func($patternselect, $address);
1075:         }
1076:         //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
1077:         if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
1078:             return false;
1079:         }
1080:         if (!$patternselect or $patternselect == 'auto') {
1081:             //Check this constant first so it works when extension_loaded() is disabled by safe mode
1082:             //Constant was added in PHP 5.2.4
1083:             if (defined('PCRE_VERSION')) {
1084:                 //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
1085:                 if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
1086:                     $patternselect = 'pcre8';
1087:                 } else {
1088:                     $patternselect = 'pcre';
1089:                 }
1090:             } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
1091:                 //Fall back to older PCRE
1092:                 $patternselect = 'pcre';
1093:             } else {
1094:                 //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
1095:                 if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
1096:                     $patternselect = 'php';
1097:                 } else {
1098:                     $patternselect = 'noregex';
1099:                 }
1100:             }
1101:         }
1102:         switch ($patternselect) {
1103:             case 'pcre8':
1104:                 /**
1105:                  * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
1106:                  * @link http://squiloople.com/2009/12/20/email-address-validation/
1107:                  * @copyright 2009-2010 Michael Rushton
1108:                  * Feel free to use and redistribute this code. But please keep this copyright notice.
1109:                  */
1110:                 return (boolean)preg_match(
1111:                     '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
1112:                     '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
1113:                     '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
1114:                     '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
1115:                     '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
1116:                     '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
1117:                     '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
1118:                     '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
1119:                     '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
1120:                     $address
1121:                 );
1122:             case 'pcre':
1123:                 //An older regex that doesn't need a recent PCRE
1124:                 return (boolean)preg_match(
1125:                     '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
1126:                     '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
1127:                     '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
1128:                     '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
1129:                     '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
1130:                     '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
1131:                     '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
1132:                     '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
1133:                     '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
1134:                     '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
1135:                     $address
1136:                 );
1137:             case 'html5':
1138:                 /**
1139:                  * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
1140:                  * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
1141:                  */
1142:                 return (boolean)preg_match(
1143:                     '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
1144:                     '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
1145:                     $address
1146:                 );
1147:             case 'noregex':
1148:                 //No PCRE! Do something _very_ approximate!
1149:                 //Check the address is 3 chars or longer and contains an @ that's not the first or last char
1150:                 return (strlen($address) >= 3
1151:                     and strpos($address, '@') >= 1
1152:                     and strpos($address, '@') != strlen($address) - 1);
1153:             case 'php':
1154:             default:
1155:                 return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
1156:         }
1157:     }
1158: 
1159:     /**
1160:      * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the
1161:      * "intl" and "mbstring" PHP extensions.
1162:      * @return bool "true" if required functions for IDN support are present
1163:      */
1164:     public function idnSupported()
1165:     {
1166:         // @TODO: Write our own "idn_to_ascii" function for PHP <= 5.2.
1167:         return function_exists('idn_to_ascii') and function_exists('mb_convert_encoding');
1168:     }
1169: 
1170:     /**
1171:      * Converts IDN in given email address to its ASCII form, also known as punycode, if possible.
1172:      * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet.
1173:      * This function silently returns unmodified address if:
1174:      * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form)
1175:      * - Conversion to punycode is impossible (e.g. required PHP functions are not available)
1176:      *   or fails for any reason (e.g. domain has characters not allowed in an IDN)
1177:      * @see PHPMailer::$CharSet
1178:      * @param string $address The email address to convert
1179:      * @return string The encoded address in ASCII form
1180:      */
1181:     public function punyencodeAddress($address)
1182:     {
1183:         // Verify we have required functions, CharSet, and at-sign.
1184:         if ($this->idnSupported() and
1185:             !empty($this->CharSet) and
1186:             ($pos = strrpos($address, '@')) !== false) {
1187:             $domain = substr($address, ++$pos);
1188:             // Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
1189:             if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) {
1190:                 $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet);
1191:                 if (($punycode = defined('INTL_IDNA_VARIANT_UTS46') ?
1192:                     idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) :
1193:                     idn_to_ascii($domain)) !== false) {
1194:                     return substr($address, 0, $pos) . $punycode;
1195:                 }
1196:             }
1197:         }
1198:         return $address;
1199:     }
1200: 
1201:     /**
1202:      * Create a message and send it.
1203:      * Uses the sending method specified by $Mailer.
1204:      * @throws phpmailerException
1205:      * @return boolean false on error - See the ErrorInfo property for details of the error.
1206:      */
1207:     public function send()
1208:     {
1209:         try {
1210:             if (!$this->preSend()) {
1211:                 return false;
1212:             }
1213:             return $this->postSend();
1214:         } catch (phpmailerException $exc) {
1215:             $this->mailHeader = '';
1216:             $this->setError($exc->getMessage());
1217:             if ($this->exceptions) {
1218:                 throw $exc;
1219:             }
1220:             return false;
1221:         }
1222:     }
1223: 
1224:     /**
1225:      * Prepare a message for sending.
1226:      * @throws phpmailerException
1227:      * @return boolean
1228:      */
1229:     public function preSend()
1230:     {
1231:         try {
1232:             $this->error_count = 0; // Reset errors
1233:             $this->mailHeader = '';
1234: 
1235:             // Dequeue recipient and Reply-To addresses with IDN
1236:             foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
1237:                 $params[1] = $this->punyencodeAddress($params[1]);
1238:                 call_user_func_array(array($this, 'addAnAddress'), $params);
1239:             }
1240:             if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
1241:                 throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL);
1242:             }
1243: 
1244:             // Validate From, Sender, and ConfirmReadingTo addresses
1245:             foreach (array('From', 'Sender', 'ConfirmReadingTo') as $address_kind) {
1246:                 $this->$address_kind = trim($this->$address_kind);
1247:                 if (empty($this->$address_kind)) {
1248:                     continue;
1249:                 }
1250:                 $this->$address_kind = $this->punyencodeAddress($this->$address_kind);
1251:                 if (!$this->validateAddress($this->$address_kind)) {
1252:                     $error_message = $this->lang('invalid_address') . ' (punyEncode) ' . $this->$address_kind;
1253:                     $this->setError($error_message);
1254:                     $this->edebug($error_message);
1255:                     if ($this->exceptions) {
1256:                         throw new phpmailerException($error_message);
1257:                     }
1258:                     return false;
1259:                 }
1260:             }
1261: 
1262:             // Set whether the message is multipart/alternative
1263:             if ($this->alternativeExists()) {
1264:                 $this->ContentType = 'multipart/alternative';
1265:             }
1266: 
1267:             $this->setMessageType();
1268:             // Refuse to send an empty message unless we are specifically allowing it
1269:             if (!$this->AllowEmpty and empty($this->Body)) {
1270:                 throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
1271:             }
1272: 
1273:             // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
1274:             $this->MIMEHeader = '';
1275:             $this->MIMEBody = $this->createBody();
1276:             // createBody may have added some headers, so retain them
1277:             $tempheaders = $this->MIMEHeader;
1278:             $this->MIMEHeader = $this->createHeader();
1279:             $this->MIMEHeader .= $tempheaders;
1280: 
1281:             // To capture the complete message when using mail(), create
1282:             // an extra header list which createHeader() doesn't fold in
1283:             if ($this->Mailer == 'mail') {
1284:                 if (count($this->to) > 0) {
1285:                     $this->mailHeader .= $this->addrAppend('To', $this->to);
1286:                 } else {
1287:                     $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
1288:                 }
1289:                 $this->mailHeader .= $this->headerLine(
1290:                     'Subject',
1291:                     $this->encodeHeader($this->secureHeader(trim($this->Subject)))
1292:                 );
1293:             }
1294: 
1295:             // Sign with DKIM if enabled
1296:             if (!empty($this->DKIM_domain)
1297:                 && !empty($this->DKIM_selector)
1298:                 && (!empty($this->DKIM_private_string)
1299:                    || (!empty($this->DKIM_private) && file_exists($this->DKIM_private))
1300:                 )
1301:             ) {
1302:                 $header_dkim = $this->DKIM_Add(
1303:                     $this->MIMEHeader . $this->mailHeader,
1304:                     $this->encodeHeader($this->secureHeader($this->Subject)),
1305:                     $this->MIMEBody
1306:                 );
1307:                 $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF .
1308:                     str_replace("\r\n", "\n", $header_dkim) . self::CRLF;
1309:             }
1310:             return true;
1311:         } catch (phpmailerException $exc) {
1312:             $this->setError($exc->getMessage());
1313:             if ($this->exceptions) {
1314:                 throw $exc;
1315:             }
1316:             return false;
1317:         }
1318:     }
1319: 
1320:     /**
1321:      * Actually send a message.
1322:      * Send the email via the selected mechanism
1323:      * @throws phpmailerException
1324:      * @return boolean
1325:      */
1326:     public function postSend()
1327:     {
1328:         try {
1329:             // Choose the mailer and send through it
1330:             switch ($this->Mailer) {
1331:                 case 'sendmail':
1332:                 case 'qmail':
1333:                     return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
1334:                 case 'smtp':
1335:                     return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
1336:                 case 'mail':
1337:                     return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
1338:                 default:
1339:                     $sendMethod = $this->Mailer.'Send';
1340:                     if (method_exists($this, $sendMethod)) {
1341:                         return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
1342:                     }
1343: 
1344:                     return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
1345:             }
1346:         } catch (phpmailerException $exc) {
1347:             $this->setError($exc->getMessage());
1348:             $this->edebug($exc->getMessage());
1349:             if ($this->exceptions) {
1350:                 throw $exc;
1351:             }
1352:         }
1353:         return false;
1354:     }
1355: 
1356:     /**
1357:      * Send mail using the $Sendmail program.
1358:      * @param string $header The message headers
1359:      * @param string $body The message body
1360:      * @see PHPMailer::$Sendmail
1361:      * @throws phpmailerException
1362:      * @access protected
1363:      * @return boolean
1364:      */
1365:     protected function sendmailSend($header, $body)
1366:     {
1367:         // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
1368:         if (!empty($this->Sender) and self::isShellSafe($this->Sender)) {
1369:             if ($this->Mailer == 'qmail') {
1370:                 $sendmailFmt = '%s -f%s';
1371:             } else {
1372:                 $sendmailFmt = '%s -oi -f%s -t';
1373:             }
1374:         } else {
1375:             if ($this->Mailer == 'qmail') {
1376:                 $sendmailFmt = '%s';
1377:             } else {
1378:                 $sendmailFmt = '%s -oi -t';
1379:             }
1380:         }
1381: 
1382:         // TODO: If possible, this should be changed to escapeshellarg.  Needs thorough testing.
1383:         $sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
1384: 
1385:         if ($this->SingleTo) {
1386:             foreach ($this->SingleToArray as $toAddr) {
1387:                 if (!@$mail = popen($sendmail, 'w')) {
1388:                     throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1389:                 }
1390:                 fputs($mail, 'To: ' . $toAddr . "\n");
1391:                 fputs($mail, $header);
1392:                 fputs($mail, $body);
1393:                 $result = pclose($mail);
1394:                 $this->doCallback(
1395:                     ($result == 0),
1396:                     array($toAddr),
1397:                     $this->cc,
1398:                     $this->bcc,
1399:                     $this->Subject,
1400:                     $body,
1401:                     $this->From
1402:                 );
1403:                 if ($result != 0) {
1404:                     throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1405:                 }
1406:             }
1407:         } else {
1408:             if (!@$mail = popen($sendmail, 'w')) {
1409:                 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1410:             }
1411:             fputs($mail, $header);
1412:             fputs($mail, $body);
1413:             $result = pclose($mail);
1414:             $this->doCallback(
1415:                 ($result == 0),
1416:                 $this->to,
1417:                 $this->cc,
1418:                 $this->bcc,
1419:                 $this->Subject,
1420:                 $body,
1421:                 $this->From
1422:             );
1423:             if ($result != 0) {
1424:                 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1425:             }
1426:         }
1427:         return true;
1428:     }
1429: 
1430:     /**
1431:      * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters.
1432:      *
1433:      * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows.
1434:      * @param string $string The string to be validated
1435:      * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report
1436:      * @access protected
1437:      * @return boolean
1438:      */
1439:     protected static function isShellSafe($string)
1440:     {
1441:         // Future-proof
1442:         if (escapeshellcmd($string) !== $string
1443:             or !in_array(escapeshellarg($string), array("'$string'", "\"$string\""))
1444:         ) {
1445:             return false;
1446:         }
1447: 
1448:         $length = strlen($string);
1449: 
1450:         for ($i = 0; $i < $length; $i++) {
1451:             $c = $string[$i];
1452: 
1453:             // All other characters have a special meaning in at least one common shell, including = and +.
1454:             // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
1455:             // Note that this does permit non-Latin alphanumeric characters based on the current locale.
1456:             if (!ctype_alnum($c) && strpos('@_-.', $c) === false) {
1457:                 return false;
1458:             }
1459:         }
1460: 
1461:         return true;
1462:     }
1463: 
1464:     /**
1465:      * Send mail using the PHP mail() function.
1466:      * @param string $header The message headers
1467:      * @param string $body The message body
1468:      * @link http://www.php.net/manual/en/book.mail.php
1469:      * @throws phpmailerException
1470:      * @access protected
1471:      * @return boolean
1472:      */
1473:     protected function mailSend($header, $body)
1474:     {
1475:         $toArr = array();
1476:         foreach ($this->to as $toaddr) {
1477:             $toArr[] = $this->addrFormat($toaddr);
1478:         }
1479:         $to = implode(', ', $toArr);
1480: 
1481:         $params = null;
1482:         //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
1483:         if (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
1484:             // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
1485:             if (self::isShellSafe($this->Sender)) {
1486:                 $params = sprintf('-f%s', $this->Sender);
1487:             }
1488:         }
1489:         if (!empty($this->Sender) and !ini_get('safe_mode') and $this->validateAddress($this->Sender)) {
1490:             $old_from = ini_get('sendmail_from');
1491:             ini_set('sendmail_from', $this->Sender);
1492:         }
1493:         $result = false;
1494:         if ($this->SingleTo and count($toArr) > 1) {
1495:             foreach ($toArr as $toAddr) {
1496:                 $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
1497:                 $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
1498:             }
1499:         } else {
1500:             $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
1501:             $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
1502:         }
1503:         if (isset($old_from)) {
1504:             ini_set('sendmail_from', $old_from);
1505:         }
1506:         if (!$result) {
1507:             throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL);
1508:         }
1509:         return true;
1510:     }
1511: 
1512:     /**
1513:      * Get an instance to use for SMTP operations.
1514:      * Override this function to load your own SMTP implementation
1515:      * @return SMTP
1516:      */
1517:     public function getSMTPInstance()
1518:     {
1519:         if (!is_object($this->smtp)) {
1520:             $this->smtp = new SMTP;
1521:         }
1522:         return $this->smtp;
1523:     }
1524: 
1525:     /**
1526:      * Send mail via SMTP.
1527:      * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
1528:      * Uses the PHPMailerSMTP class by default.
1529:      * @see PHPMailer::getSMTPInstance() to use a different class.
1530:      * @param string $header The message headers
1531:      * @param string $body The message body
1532:      * @throws phpmailerException
1533:      * @uses SMTP
1534:      * @access protected
1535:      * @return boolean
1536:      */
1537:     protected function smtpSend($header, $body)
1538:     {
1539:         $bad_rcpt = array();
1540:         if (!$this->smtpConnect($this->SMTPOptions)) {
1541:             throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
1542:         }
1543:         if (!empty($this->Sender) and $this->validateAddress($this->Sender)) {
1544:             $smtp_from = $this->Sender;
1545:         } else {
1546:             $smtp_from = $this->From;
1547:         }
1548:         if (!$this->smtp->mail($smtp_from)) {
1549:             $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
1550:             throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
1551:         }
1552: 
1553:         // Attempt to send to all recipients
1554:         foreach (array($this->to, $this->cc, $this->bcc) as $togroup) {
1555:             foreach ($togroup as $to) {
1556:                 if (!$this->smtp->recipient($to[0])) {
1557:                     $error = $this->smtp->getError();
1558:                     $bad_rcpt[] = array('to' => $to[0], 'error' => $error['detail']);
1559:                     $isSent = false;
1560:                 } else {
1561:                     $isSent = true;
1562:                 }
1563:                 $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From);
1564:             }
1565:         }
1566: 
1567:         // Only send the DATA command if we have viable recipients
1568:         if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
1569:             throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL);
1570:         }
1571:         if ($this->SMTPKeepAlive) {
1572:             $this->smtp->reset();
1573:         } else {
1574:             $this->smtp->quit();
1575:             $this->smtp->close();
1576:         }
1577:         //Create error message for any bad addresses
1578:         if (count($bad_rcpt) > 0) {
1579:             $errstr = '';
1580:             foreach ($bad_rcpt as $bad) {
1581:                 $errstr .= $bad['to'] . ': ' . $bad['error'];
1582:             }
1583:             throw new phpmailerException(
1584:                 $this->lang('recipients_failed') . $errstr,
1585:                 self::STOP_CONTINUE
1586:             );
1587:         }
1588:         return true;
1589:     }
1590: 
1591:     /**
1592:      * Initiate a connection to an SMTP server.
1593:      * Returns false if the operation failed.
1594:      * @param array $options An array of options compatible with stream_context_create()
1595:      * @uses SMTP
1596:      * @access public
1597:      * @throws phpmailerException
1598:      * @return boolean
1599:      */
1600:     public function smtpConnect($options = null)
1601:     {
1602:         if (is_null($this->smtp)) {
1603:             $this->smtp = $this->getSMTPInstance();
1604:         }
1605: 
1606:         //If no options are provided, use whatever is set in the instance
1607:         if (is_null($options)) {
1608:             $options = $this->SMTPOptions;
1609:         }
1610: 
1611:         // Already connected?
1612:         if ($this->smtp->connected()) {
1613:             return true;
1614:         }
1615: 
1616:         $this->smtp->setTimeout($this->Timeout);
1617:         $this->smtp->setDebugLevel($this->SMTPDebug);
1618:         $this->smtp->setDebugOutput($this->Debugoutput);
1619:         $this->smtp->setVerp($this->do_verp);
1620:         $hosts = explode(';', $this->Host);
1621:         $lastexception = null;
1622: 
1623:         foreach ($hosts as $hostentry) {
1624:             $hostinfo = array();
1625:             if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
1626:                 // Not a valid host entry
1627:                 continue;
1628:             }
1629:             // $hostinfo[2]: optional ssl or tls prefix
1630:             // $hostinfo[3]: the hostname
1631:             // $hostinfo[4]: optional port number
1632:             // The host string prefix can temporarily override the current setting for SMTPSecure
1633:             // If it's not specified, the default value is used
1634:             $prefix = '';
1635:             $secure = $this->SMTPSecure;
1636:             $tls = ($this->SMTPSecure == 'tls');
1637:             if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
1638:                 $prefix = 'ssl://';
1639:                 $tls = false; // Can't have SSL and TLS at the same time
1640:                 $secure = 'ssl';
1641:             } elseif ($hostinfo[2] == 'tls') {
1642:                 $tls = true;
1643:                 // tls doesn't use a prefix
1644:                 $secure = 'tls';
1645:             }
1646:             //Do we need the OpenSSL extension?
1647:             $sslext = defined('OPENSSL_ALGO_SHA1');
1648:             if ('tls' === $secure or 'ssl' === $secure) {
1649:                 //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
1650:                 if (!$sslext) {
1651:                     throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
1652:                 }
1653:             }
1654:             $host = $hostinfo[3];
1655:             $port = $this->Port;
1656:             $tport = (integer)$hostinfo[4];
1657:             if ($tport > 0 and $tport < 65536) {
1658:                 $port = $tport;
1659:             }
1660:             if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
1661:                 try {
1662:                     if ($this->Helo) {
1663:                         $hello = $this->Helo;
1664:                     } else {
1665:                         $hello = $this->serverHostname();
1666:                     }
1667:                     $this->smtp->hello($hello);
1668:                     //Automatically enable TLS encryption if:
1669:                     // * it's not disabled
1670:                     // * we have openssl extension
1671:                     // * we are not already using SSL
1672:                     // * the server offers STARTTLS
1673:                     if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) {
1674:                         $tls = true;
1675:                     }
1676:                     if ($tls) {
1677:                         if (!$this->smtp->startTLS()) {
1678:                             throw new phpmailerException($this->lang('connect_host'));
1679:                         }
1680:                         // We must resend EHLO after TLS negotiation
1681:                         $this->smtp->hello($hello);
1682:                     }
1683:                     if ($this->SMTPAuth) {
1684:                         if (!$this->smtp->authenticate(
1685:                             $this->Username,
1686:                             $this->Password,
1687:                             $this->AuthType,
1688:                             $this->Realm,
1689:                             $this->Workstation
1690:                         )
1691:                         ) {
1692:                             throw new phpmailerException($this->lang('authenticate'));
1693:                         }
1694:                     }
1695:                     return true;
1696:                 } catch (phpmailerException $exc) {
1697:                     $lastexception = $exc;
1698:                     $this->edebug($exc->getMessage());
1699:                     // We must have connected, but then failed TLS or Auth, so close connection nicely
1700:                     $this->smtp->quit();
1701:                 }
1702:             }
1703:         }
1704:         // If we get here, all connection attempts have failed, so close connection hard
1705:         $this->smtp->close();
1706:         // As we've caught all exceptions, just report whatever the last one was
1707:         if ($this->exceptions and !is_null($lastexception)) {
1708:             throw $lastexception;
1709:         }
1710:         return false;
1711:     }
1712: 
1713:     /**
1714:      * Close the active SMTP session if one exists.
1715:      * @return void
1716:      */
1717:     public function smtpClose()
1718:     {
1719:         if (is_a($this->smtp, 'SMTP')) {
1720:             if ($this->smtp->connected()) {
1721:                 $this->smtp->quit();
1722:                 $this->smtp->close();
1723:             }
1724:         }
1725:     }
1726: 
1727:     /**
1728:      * Set the language for error messages.
1729:      * Returns false if it cannot load the language file.
1730:      * The default language is English.
1731:      * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
1732:      * @param string $lang_path Path to the language file directory, with trailing separator (slash)
1733:      * @return boolean
1734:      * @access public
1735:      */
1736:     public function setLanguage($langcode = 'en', $lang_path = '')
1737:     {
1738:         // Backwards compatibility for renamed language codes
1739:         $renamed_langcodes = array(
1740:             'br' => 'pt_br',
1741:             'cz' => 'cs',
1742:             'dk' => 'da',
1743:             'no' => 'nb',
1744:             'se' => 'sv',
1745:         );
1746: 
1747:         if (isset($renamed_langcodes[$langcode])) {
1748:             $langcode = $renamed_langcodes[$langcode];
1749:         }
1750: 
1751:         // Define full set of translatable strings in English
1752:         $PHPMAILER_LANG = array(
1753:             'authenticate' => 'SMTP Error: Could not authenticate.',
1754:             'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
1755:             'data_not_accepted' => 'SMTP Error: data not accepted.',
1756:             'empty_message' => 'Message body empty',
1757:             'encoding' => 'Unknown encoding: ',
1758:             'execute' => 'Could not execute: ',
1759:             'file_access' => 'Could not access file: ',
1760:             'file_open' => 'File Error: Could not open file: ',
1761:             'from_failed' => 'The following From address failed: ',
1762:             'instantiate' => 'Could not instantiate mail function.',
1763:             'invalid_address' => 'Invalid address: ',
1764:             'mailer_not_supported' => ' mailer is not supported.',
1765:             'provide_address' => 'You must provide at least one recipient email address.',
1766:             'recipients_failed' => 'SMTP Error: The following recipients failed: ',
1767:             'signing' => 'Signing Error: ',
1768:             'smtp_connect_failed' => 'SMTP connect() failed.',
1769:             'smtp_error' => 'SMTP server error: ',
1770:             'variable_set' => 'Cannot set or reset variable: ',
1771:             'extension_missing' => 'Extension missing: '
1772:         );
1773:         if (empty($lang_path)) {
1774:             // Calculate an absolute path so it can work if CWD is not here
1775:             $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
1776:         }
1777:         //Validate $langcode
1778:         if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) {
1779:             $langcode = 'en';
1780:         }
1781:         $foundlang = true;
1782:         $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
1783:         // There is no English translation file
1784:         if ($langcode != 'en') {
1785:             // Make sure language file path is readable
1786:             if (!is_readable($lang_file)) {
1787:                 $foundlang = false;
1788:             } else {
1789:                 // Overwrite language-specific strings.
1790:                 // This way we'll never have missing translation keys.
1791:                 $foundlang = include $lang_file;
1792:             }
1793:         }
1794:         $this->language = $PHPMAILER_LANG;
1795:         return (boolean)$foundlang; // Returns false if language not found
1796:     }
1797: 
1798:     /**
1799:      * Get the array of strings for the current language.
1800:      * @return array
1801:      */
1802:     public function getTranslations()
1803:     {
1804:         return $this->language;
1805:     }
1806: 
1807:     /**
1808:      * Create recipient headers.
1809:      * @access public
1810:      * @param string $type
1811:      * @param array $addr An array of recipient,
1812:      * where each recipient is a 2-element indexed array with element 0 containing an address
1813:      * and element 1 containing a name, like:
1814:      * array(array('joe@example.com', 'Joe User'), array('zoe@example.com', 'Zoe User'))
1815:      * @return string
1816:      */
1817:     public function addrAppend($type, $addr)
1818:     {
1819:         $addresses = array();
1820:         foreach ($addr as $address) {
1821:             $addresses[] = $this->addrFormat($address);
1822:         }
1823:         return $type . ': ' . implode(', ', $addresses) . $this->LE;
1824:     }
1825: 
1826:     /**
1827:      * Format an address for use in a message header.
1828:      * @access public
1829:      * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name
1830:      *      like array('joe@example.com', 'Joe User')
1831:      * @return string
1832:      */
1833:     public function addrFormat($addr)
1834:     {
1835:         if (empty($addr[1])) { // No name provided
1836:             return $this->secureHeader($addr[0]);
1837:         } else {
1838:             return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader(
1839:                 $addr[0]
1840:             ) . '>';
1841:         }
1842:     }
1843: 
1844:     /**
1845:      * Word-wrap message.
1846:      * For use with mailers that do not automatically perform wrapping
1847:      * and for quoted-printable encoded messages.
1848:      * Original written by philippe.
1849:      * @param string $message The message to wrap
1850:      * @param integer $length The line length to wrap to
1851:      * @param boolean $qp_mode Whether to run in Quoted-Printable mode
1852:      * @access public
1853:      * @return string
1854:      */
1855:     public function wrapText($message, $length, $qp_mode = false)
1856:     {
1857:         if ($qp_mode) {
1858:             $soft_break = sprintf(' =%s', $this->LE);
1859:         } else {
1860:             $soft_break = $this->LE;
1861:         }
1862:         // If utf-8 encoding is used, we will need to make sure we don't
1863:         // split multibyte characters when we wrap
1864:         $is_utf8 = (strtolower($this->CharSet) == 'utf-8');
1865:         $lelen = strlen($this->LE);
1866:         $crlflen = strlen(self::CRLF);
1867: 
1868:         $message = $this->fixEOL($message);
1869:         //Remove a trailing line break
1870:         if (substr($message, -$lelen) == $this->LE) {
1871:             $message = substr($message, 0, -$lelen);
1872:         }
1873: 
1874:         //Split message into lines
1875:         $lines = explode($this->LE, $message);
1876:         //Message will be rebuilt in here
1877:         $message = '';
1878:         foreach ($lines as $line) {
1879:             $words = explode(' ', $line);
1880:             $buf = '';
1881:             $firstword = true;
1882:             foreach ($words as $word) {
1883:                 if ($qp_mode and (strlen($word) > $length)) {
1884:                     $space_left = $length - strlen($buf) - $crlflen;
1885:                     if (!$firstword) {
1886:                         if ($space_left > 20) {
1887:                             $len = $space_left;
1888:                             if ($is_utf8) {
1889:                                 $len = $this->utf8CharBoundary($word, $len);
1890:                             } elseif (substr($word, $len - 1, 1) == '=') {
1891:                                 $len--;
1892:                             } elseif (substr($word, $len - 2, 1) == '=') {
1893:                                 $len -= 2;
1894:                             }
1895:                             $part = substr($word, 0, $len);
1896:                             $word = substr($word, $len);
1897:                             $buf .= ' ' . $part;
1898:                             $message .= $buf . sprintf('=%s', self::CRLF);
1899:                         } else {
1900:                             $message .= $buf . $soft_break;
1901:                         }
1902:                         $buf = '';
1903:                     }
1904:                     while (strlen($word) > 0) {
1905:                         if ($length <= 0) {
1906:                             break;
1907:                         }
1908:                         $len = $length;
1909:                         if ($is_utf8) {
1910:                             $len = $this->utf8CharBoundary($word, $len);
1911:                         } elseif (substr($word, $len - 1, 1) == '=') {
1912:                             $len--;
1913:                         } elseif (substr($word, $len - 2, 1) == '=') {
1914:                             $len -= 2;
1915:                         }
1916:                         $part = substr($word, 0, $len);
1917:                         $word = substr($word, $len);
1918: 
1919:                         if (strlen($word) > 0) {
1920:                             $message .= $part . sprintf('=%s', self::CRLF);
1921:                         } else {
1922:                             $buf = $part;
1923:                         }
1924:                     }
1925:                 } else {
1926:                     $buf_o = $buf;
1927:                     if (!$firstword) {
1928:                         $buf .= ' ';
1929:                     }
1930:                     $buf .= $word;
1931: 
1932:                     if (strlen($buf) > $length and $buf_o != '') {
1933:                         $message .= $buf_o . $soft_break;
1934:                         $buf = $word;
1935:                     }
1936:                 }
1937:                 $firstword = false;
1938:             }
1939:             $message .= $buf . self::CRLF;
1940:         }
1941: 
1942:         return $message;
1943:     }
1944: 
1945:     /**
1946:      * Find the last character boundary prior to $maxLength in a utf-8
1947:      * quoted-printable encoded string.
1948:      * Original written by Colin Brown.
1949:      * @access public
1950:      * @param string $encodedText utf-8 QP text
1951:      * @param integer $maxLength Find the last character boundary prior to this length
1952:      * @return integer
1953:      */
1954:     public function utf8CharBoundary($encodedText, $maxLength)
1955:     {
1956:         $foundSplitPos = false;
1957:         $lookBack = 3;
1958:         while (!$foundSplitPos) {
1959:             $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
1960:             $encodedCharPos = strpos($lastChunk, '=');
1961:             if (false !== $encodedCharPos) {
1962:                 // Found start of encoded character byte within $lookBack block.
1963:                 // Check the encoded byte value (the 2 chars after the '=')
1964:                 $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
1965:                 $dec = hexdec($hex);
1966:                 if ($dec < 128) {
1967:                     // Single byte character.
1968:                     // If the encoded char was found at pos 0, it will fit
1969:                     // otherwise reduce maxLength to start of the encoded char
1970:                     if ($encodedCharPos > 0) {
1971:                         $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1972:                     }
1973:                     $foundSplitPos = true;
1974:                 } elseif ($dec >= 192) {
1975:                     // First byte of a multi byte character
1976:                     // Reduce maxLength to split at start of character
1977:                     $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1978:                     $foundSplitPos = true;
1979:                 } elseif ($dec < 192) {
1980:                     // Middle byte of a multi byte character, look further back
1981:                     $lookBack += 3;
1982:                 }
1983:             } else {
1984:                 // No encoded character found
1985:                 $foundSplitPos = true;
1986:             }
1987:         }
1988:         return $maxLength;
1989:     }
1990: 
1991:     /**
1992:      * Apply word wrapping to the message body.
1993:      * Wraps the message body to the number of chars set in the WordWrap property.
1994:      * You should only do this to plain-text bodies as wrapping HTML tags may break them.
1995:      * This is called automatically by createBody(), so you don't need to call it yourself.
1996:      * @access public
1997:      * @return void
1998:      */
1999:     public function setWordWrap()
2000:     {
2001:         if ($this->WordWrap < 1) {
2002:             return;
2003:         }
2004: 
2005:         switch ($this->message_type) {
2006:             case 'alt':
2007:             case 'alt_inline':
2008:             case 'alt_attach':
2009:             case 'alt_inline_attach':
2010:                 $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
2011:                 break;
2012:             default:
2013:                 $this->Body = $this->wrapText($this->Body, $this->WordWrap);
2014:                 break;
2015:         }
2016:     }
2017: 
2018:     /**
2019:      * Assemble message headers.
2020:      * @access public
2021:      * @return string The assembled headers
2022:      */
2023:     public function createHeader()
2024:     {
2025:         $result = '';
2026: 
2027:         if ($this->MessageDate == '') {
2028:             $this->MessageDate = self::rfcDate();
2029:         }
2030:         $result .= $this->headerLine('Date', $this->MessageDate);
2031: 
2032:         // To be created automatically by mail()
2033:         if ($this->SingleTo) {
2034:             if ($this->Mailer != 'mail') {
2035:                 foreach ($this->to as $toaddr) {
2036:                     $this->SingleToArray[] = $this->addrFormat($toaddr);
2037:                 }
2038:             }
2039:         } else {
2040:             if (count($this->to) > 0) {
2041:                 if ($this->Mailer != 'mail') {
2042:                     $result .= $this->addrAppend('To', $this->to);
2043:                 }
2044:             } elseif (count($this->cc) == 0) {
2045:                 $result .= $this->headerLine('To', 'undisclosed-recipients:;');
2046:             }
2047:         }
2048: 
2049:         $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName)));
2050: 
2051:         // sendmail and mail() extract Cc from the header before sending
2052:         if (count($this->cc) > 0) {
2053:             $result .= $this->addrAppend('Cc', $this->cc);
2054:         }
2055: 
2056:         // sendmail and mail() extract Bcc from the header before sending
2057:         if ((
2058:                 $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail'
2059:             )
2060:             and count($this->bcc) > 0
2061:         ) {
2062:             $result .= $this->addrAppend('Bcc', $this->bcc);
2063:         }
2064: 
2065:         if (count($this->ReplyTo) > 0) {
2066:             $result .= $this->addrAppend('Reply-To', $this->ReplyTo);
2067:         }
2068: 
2069:         // mail() sets the subject itself
2070:         if ($this->Mailer != 'mail') {
2071:             $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
2072:         }
2073: 
2074:         // Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
2075:         // https://tools.ietf.org/html/rfc5322#section-3.6.4
2076:         if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) {
2077:             $this->lastMessageID = $this->MessageID;
2078:         } else {
2079:             $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname());
2080:         }
2081:         $result .= $this->headerLine('Message-ID', $this->lastMessageID);
2082:         if (!is_null($this->Priority)) {
2083:             $result .= $this->headerLine('X-Priority', $this->Priority);
2084:         }
2085:         if ($this->XMailer == '') {
2086:             $result .= $this->headerLine(
2087:                 'X-Mailer',
2088:                 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer)'
2089:             );
2090:         } else {
2091:             $myXmailer = trim($this->XMailer);
2092:             if ($myXmailer) {
2093:                 $result .= $this->headerLine('X-Mailer', $myXmailer);
2094:             }
2095:         }
2096: 
2097:         if ($this->ConfirmReadingTo != '') {
2098:             $result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>');
2099:         }
2100: 
2101:         // Add custom headers
2102:         foreach ($this->CustomHeader as $header) {
2103:             $result .= $this->headerLine(
2104:                 trim($header[0]),
2105:                 $this->encodeHeader(trim($header[1]))
2106:             );
2107:         }
2108:         if (!$this->sign_key_file) {
2109:             $result .= $this->headerLine('MIME-Version', '1.0');
2110:             $result .= $this->getMailMIME();
2111:         }
2112: 
2113:         return $result;
2114:     }
2115: 
2116:     /**
2117:      * Get the message MIME type headers.
2118:      * @access public
2119:      * @return string
2120:      */
2121:     public function getMailMIME()
2122:     {
2123:         $result = '';
2124:         $ismultipart = true;
2125:         switch ($this->message_type) {
2126:             case 'inline':
2127:                 $result .= $this->headerLine('Content-Type', 'multipart/related;');
2128:                 $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
2129:                 break;
2130:             case 'attach':
2131:             case 'inline_attach':
2132:             case 'alt_attach':
2133:             case 'alt_inline_attach':
2134:                 $result .= $this->headerLine('Content-Type', 'multipart/mixed;');
2135:                 $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
2136:                 break;
2137:             case 'alt':
2138:             case 'alt_inline':
2139:                 $result .= $this->headerLine('Content-Type', 'multipart/alternative;');
2140:                 $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
2141:                 break;
2142:             default:
2143:                 // Catches case 'plain': and case '':
2144:                 $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
2145:                 $ismultipart = false;
2146:                 break;
2147:         }
2148:         // RFC1341 part 5 says 7bit is assumed if not specified
2149:         if ($this->Encoding != '7bit') {
2150:             // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
2151:             if ($ismultipart) {
2152:                 if ($this->Encoding == '8bit') {
2153:                     $result .= $this->headerLine('Content-Transfer-Encoding', '8bit');
2154:                 }
2155:                 // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
2156:             } else {
2157:                 $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding);
2158:             }
2159:         }
2160: 
2161:         if ($this->Mailer != 'mail') {
2162:             $result .= $this->LE;
2163:         }
2164: 
2165:         return $result;
2166:     }
2167: 
2168:     /**
2169:      * Returns the whole MIME message.
2170:      * Includes complete headers and body.
2171:      * Only valid post preSend().
2172:      * @see PHPMailer::preSend()
2173:      * @access public
2174:      * @return string
2175:      */
2176:     public function getSentMIMEMessage()
2177:     {
2178:         return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . self::CRLF . self::CRLF . $this->MIMEBody;
2179:     }
2180: 
2181:     /**
2182:      * Create unique ID
2183:      * @return string
2184:      */
2185:     protected function generateId() {
2186:         return md5(uniqid(time()));
2187:     }
2188: 
2189:     /**
2190:      * Assemble the message body.
2191:      * Returns an empty string on failure.
2192:      * @access public
2193:      * @throws phpmailerException
2194:      * @return string The assembled message body
2195:      */
2196:     public function createBody()
2197:     {
2198:         $body = '';
2199:         //Create unique IDs and preset boundaries
2200:         $this->uniqueid = $this->generateId();
2201:         $this->boundary[1] = 'b1_' . $this->uniqueid;
2202:         $this->boundary[2] = 'b2_' . $this->uniqueid;
2203:         $this->boundary[3] = 'b3_' . $this->uniqueid;
2204: 
2205:         if ($this->sign_key_file) {
2206:             $body .= $this->getMailMIME() . $this->LE;
2207:         }
2208: 
2209:         $this->setWordWrap();
2210: 
2211:         $bodyEncoding = $this->Encoding;
2212:         $bodyCharSet = $this->CharSet;
2213:         //Can we do a 7-bit downgrade?
2214:         if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
2215:             $bodyEncoding = '7bit';
2216:             //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
2217:             $bodyCharSet = 'us-ascii';
2218:         }
2219:         //If lines are too long, and we're not already using an encoding that will shorten them,
2220:         //change to quoted-printable transfer encoding for the body part only
2221:         if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) {
2222:             $bodyEncoding = 'quoted-printable';
2223:         }
2224: 
2225:         $altBodyEncoding = $this->Encoding;
2226:         $altBodyCharSet = $this->CharSet;
2227:         //Can we do a 7-bit downgrade?
2228:         if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
2229:             $altBodyEncoding = '7bit';
2230:             //All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
2231:             $altBodyCharSet = 'us-ascii';
2232:         }
2233:         //If lines are too long, and we're not already using an encoding that will shorten them,
2234:         //change to quoted-printable transfer encoding for the alt body part only
2235:         if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) {
2236:             $altBodyEncoding = 'quoted-printable';
2237:         }
2238:         //Use this as a preamble in all multipart message types
2239:         $mimepre = "This is a multi-part message in MIME format." . $this->LE . $this->LE;
2240:         switch ($this->message_type) {
2241:             case 'inline':
2242:                 $body .= $mimepre;
2243:                 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
2244:                 $body .= $this->encodeString($this->Body, $bodyEncoding);
2245:                 $body .= $this->LE . $this->LE;
2246:                 $body .= $this->attachAll('inline', $this->boundary[1]);
2247:                 break;
2248:             case 'attach':
2249:                 $body .= $mimepre;
2250:                 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
2251:                 $body .= $this->encodeString($this->Body, $bodyEncoding);
2252:                 $body .= $this->LE . $this->LE;
2253:                 $body .= $this->attachAll('attachment', $this->boundary[1]);
2254:                 break;
2255:             case 'inline_attach':
2256:                 $body .= $mimepre;
2257:                 $body .= $this->textLine('--' . $this->boundary[1]);
2258:                 $body .= $this->headerLine('Content-Type', 'multipart/related;');
2259:                 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
2260:                 $body .= $this->LE;
2261:                 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
2262:                 $body .= $this->encodeString($this->Body, $bodyEncoding);
2263:                 $body .= $this->LE . $this->LE;
2264:                 $body .= $this->attachAll('inline', $this->boundary[2]);
2265:                 $body .= $this->LE;
2266:                 $body .= $this->attachAll('attachment', $this->boundary[1]);
2267:                 break;
2268:             case 'alt':
2269:                 $body .= $mimepre;
2270:                 $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
2271:                 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
2272:                 $body .= $this->LE . $this->LE;
2273:                 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
2274:                 $body .= $this->encodeString($this->Body, $bodyEncoding);
2275:                 $body .= $this->LE . $this->LE;
2276:                 if (!empty($this->Ical)) {
2277:                     $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
2278:                     $body .= $this->encodeString($this->Ical, $this->Encoding);
2279:                     $body .= $this->LE . $this->LE;
2280:                 }
2281:                 $body .= $this->endBoundary($this->boundary[1]);
2282:                 break;
2283:             case 'alt_inline':
2284:                 $body .= $mimepre;
2285:                 $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
2286:                 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
2287:                 $body .= $this->LE . $this->LE;
2288:                 $body .= $this->textLine('--' . $this->boundary[1]);
2289:                 $body .= $this->headerLine('Content-Type', 'multipart/related;');
2290:                 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
2291:                 $body .= $this->LE;
2292:                 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
2293:                 $body .= $this->encodeString($this->Body, $bodyEncoding);
2294:                 $body .= $this->LE . $this->LE;
2295:                 $body .= $this->attachAll('inline', $this->boundary[2]);
2296:                 $body .= $this->LE;
2297:                 $body .= $this->endBoundary($this->boundary[1]);
2298:                 break;
2299:             case 'alt_attach':
2300:                 $body .= $mimepre;
2301:                 $body .= $this->textLine('--' . $this->boundary[1]);
2302:                 $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
2303:                 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
2304:                 $body .= $this->LE;
2305:                 $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
2306:                 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
2307:                 $body .= $this->LE . $this->LE;
2308:                 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
2309:                 $body .= $this->encodeString($this->Body, $bodyEncoding);
2310:                 $body .= $this->LE . $this->LE;
2311:                 $body .= $this->endBoundary($this->boundary[2]);
2312:                 $body .= $this->LE;
2313:                 $body .= $this->attachAll('attachment', $this->boundary[1]);
2314:                 break;
2315:             case 'alt_inline_attach':
2316:                 $body .= $mimepre;
2317:                 $body .= $this->textLine('--' . $this->boundary[1]);
2318:                 $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
2319:                 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
2320:                 $body .= $this->LE;
2321:                 $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
2322:                 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
2323:                 $body .= $this->LE . $this->LE;
2324:                 $body .= $this->textLine('--' . $this->boundary[2]);
2325:                 $body .= $this->headerLine('Content-Type', 'multipart/related;');
2326:                 $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
2327:                 $body .= $this->LE;
2328:                 $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
2329:                 $body .= $this->encodeString($this->Body, $bodyEncoding);
2330:                 $body .= $this->LE . $this->LE;
2331:                 $body .= $this->attachAll('inline', $this->boundary[3]);
2332:                 $body .= $this->LE;
2333:                 $body .= $this->endBoundary($this->boundary[2]);
2334:                 $body .= $this->LE;
2335:                 $body .= $this->attachAll('attachment', $this->boundary[1]);
2336:                 break;
2337:             default:
2338:                 // Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
2339:                 //Reset the `Encoding` property in case we changed it for line length reasons
2340:                 $this->Encoding = $bodyEncoding;
2341:                 $body .= $this->encodeString($this->Body, $this->Encoding);
2342:                 break;
2343:         }
2344: 
2345:         if ($this->isError()) {
2346:             $body = '';
2347:         } elseif ($this->sign_key_file) {
2348:             try {
2349:                 if (!defined('PKCS7_TEXT')) {
2350:                     throw new phpmailerException($this->lang('extension_missing') . 'openssl');
2351:                 }
2352:                 // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1
2353:                 $file = tempnam(sys_get_temp_dir(), 'mail');
2354:                 if (false === file_put_contents($file, $body)) {
2355:                     throw new phpmailerException($this->lang('signing') . ' Could not write temp file');
2356:                 }
2357:                 $signed = tempnam(sys_get_temp_dir(), 'signed');
2358:                 //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197
2359:                 if (empty($this->sign_extracerts_file)) {
2360:                     $sign = @openssl_pkcs7_sign(
2361:                         $file,
2362:                         $signed,
2363:                         'file://' . realpath($this->sign_cert_file),
2364:                         array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
2365:                         null
2366:                     );
2367:                 } else {
2368:                     $sign = @openssl_pkcs7_sign(
2369:                         $file,
2370:                         $signed,
2371:                         'file://' . realpath($this->sign_cert_file),
2372:                         array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
2373:                         null,
2374:                         PKCS7_DETACHED,
2375:                         $this->sign_extracerts_file
2376:                     );
2377:                 }
2378:                 if ($sign) {
2379:                     @unlink($file);
2380:                     $body = file_get_contents($signed);
2381:                     @unlink($signed);
2382:                     //The message returned by openssl contains both headers and body, so need to split them up
2383:                     $parts = explode("\n\n", $body, 2);
2384:                     $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
2385:                     $body = $parts[1];
2386:                 } else {
2387:                     @unlink($file);
2388:                     @unlink($signed);
2389:                     throw new phpmailerException($this->lang('signing') . openssl_error_string());
2390:                 }
2391:             } catch (phpmailerException $exc) {
2392:                 $body = '';
2393:                 if ($this->exceptions) {
2394:                     throw $exc;
2395:                 }
2396:             }
2397:         }
2398:         return $body;
2399:     }
2400: 
2401:     /**
2402:      * Return the start of a message boundary.
2403:      * @access protected
2404:      * @param string $boundary
2405:      * @param string $charSet
2406:      * @param string $contentType
2407:      * @param string $encoding
2408:      * @return string
2409:      */
2410:     protected function getBoundary($boundary, $charSet, $contentType, $encoding)
2411:     {
2412:         $result = '';
2413:         if ($charSet == '') {
2414:             $charSet = $this->CharSet;
2415:         }
2416:         if ($contentType == '') {
2417:             $contentType = $this->ContentType;
2418:         }
2419:         if ($encoding == '') {
2420:             $encoding = $this->Encoding;
2421:         }
2422:         $result .= $this->textLine('--' . $boundary);
2423:         $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
2424:         $result .= $this->LE;
2425:         // RFC1341 part 5 says 7bit is assumed if not specified
2426:         if ($encoding != '7bit') {
2427:             $result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
2428:         }
2429:         $result .= $this->LE;
2430: 
2431:         return $result;
2432:     }
2433: 
2434:     /**
2435:      * Return the end of a message boundary.
2436:      * @access protected
2437:      * @param string $boundary
2438:      * @return string
2439:      */
2440:     protected function endBoundary($boundary)
2441:     {
2442:         return $this->LE . '--' . $boundary . '--' . $this->LE;
2443:     }
2444: 
2445:     /**
2446:      * Set the message type.
2447:      * PHPMailer only supports some preset message types, not arbitrary MIME structures.
2448:      * @access protected
2449:      * @return void
2450:      */
2451:     protected function setMessageType()
2452:     {
2453:         $type = array();
2454:         if ($this->alternativeExists()) {
2455:             $type[] = 'alt';
2456:         }
2457:         if ($this->inlineImageExists()) {
2458:             $type[] = 'inline';
2459:         }
2460:         if ($this->attachmentExists()) {
2461:             $type[] = 'attach';
2462:         }
2463:         $this->message_type = implode('_', $type);
2464:         if ($this->message_type == '') {
2465:             //The 'plain' message_type refers to the message having a single body element, not that it is plain-text
2466:             $this->message_type = 'plain';
2467:         }
2468:     }
2469: 
2470:     /**
2471:      * Format a header line.
2472:      * @access public
2473:      * @param string $name
2474:      * @param string $value
2475:      * @return string
2476:      */
2477:     public function headerLine($name, $value)
2478:     {
2479:         return $name . ': ' . $value . $this->LE;
2480:     }
2481: 
2482:     /**
2483:      * Return a formatted mail line.
2484:      * @access public
2485:      * @param string $value
2486:      * @return string
2487:      */
2488:     public function textLine($value)
2489:     {
2490:         return $value . $this->LE;
2491:     }
2492: 
2493:     /**
2494:      * Add an attachment from a path on the filesystem.
2495:      * Never use a user-supplied path to a file!
2496:      * Returns false if the file could not be found or read.
2497:      * @param string $path Path to the attachment.
2498:      * @param string $name Overrides the attachment name.
2499:      * @param string $encoding File encoding (see $Encoding).
2500:      * @param string $type File extension (MIME) type.
2501:      * @param string $disposition Disposition to use
2502:      * @throws phpmailerException
2503:      * @return boolean
2504:      */
2505:     public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
2506:     {
2507:         try {
2508:             if (!@is_file($path)) {
2509:                 throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE);
2510:             }
2511: 
2512:             // If a MIME type is not specified, try to work it out from the file name
2513:             if ($type == '') {
2514:                 $type = self::filenameToType($path);
2515:             }
2516: 
2517:             $filename = basename($path);
2518:             if ($name == '') {
2519:                 $name = $filename;
2520:             }
2521: 
2522:             $this->attachment[] = array(
2523:                 0 => $path,
2524:                 1 => $filename,
2525:                 2 => $name,
2526:                 3 => $encoding,
2527:                 4 => $type,
2528:                 5 => false, // isStringAttachment
2529:                 6 => $disposition,
2530:                 7 => 0
2531:             );
2532: 
2533:         } catch (phpmailerException $exc) {
2534:             $this->setError($exc->getMessage());
2535:             $this->edebug($exc->getMessage());
2536:             if ($this->exceptions) {
2537:                 throw $exc;
2538:             }
2539:             return false;
2540:         }
2541:         return true;
2542:     }
2543: 
2544:     /**
2545:      * Return the array of attachments.
2546:      * @return array
2547:      */
2548:     public function getAttachments()
2549:     {
2550:         return $this->attachment;
2551:     }
2552: 
2553:     /**
2554:      * Attach all file, string, and binary attachments to the message.
2555:      * Returns an empty string on failure.
2556:      * @access protected
2557:      * @param string $disposition_type
2558:      * @param string $boundary
2559:      * @return string
2560:      */
2561:     protected function attachAll($disposition_type, $boundary)
2562:     {
2563:         // Return text of body
2564:         $mime = array();
2565:         $cidUniq = array();
2566:         $incl = array();
2567: 
2568:         // Add all attachments
2569:         foreach ($this->attachment as $attachment) {
2570:             // Check if it is a valid disposition_filter
2571:             if ($attachment[6] == $disposition_type) {
2572:                 // Check for string attachment
2573:                 $string = '';
2574:                 $path = '';
2575:                 $bString = $attachment[5];
2576:                 if ($bString) {
2577:                     $string = $attachment[0];
2578:                 } else {
2579:                     $path = $attachment[0];
2580:                 }
2581: 
2582:                 $inclhash = md5(serialize($attachment));
2583:                 if (in_array($inclhash, $incl)) {
2584:                     continue;
2585:                 }
2586:                 $incl[] = $inclhash;
2587:                 $name = $attachment[2];
2588:                 $encoding = $attachment[3];
2589:                 $type = $attachment[4];
2590:                 $disposition = $attachment[6];
2591:                 $cid = $attachment[7];
2592:                 if ($disposition == 'inline' && array_key_exists($cid, $cidUniq)) {
2593:                     continue;
2594:                 }
2595:                 $cidUniq[$cid] = true;
2596: 
2597:                 $mime[] = sprintf('--%s%s', $boundary, $this->LE);
2598:                 //Only include a filename property if we have one
2599:                 if (!empty($name)) {
2600:                     $mime[] = sprintf(
2601:                         'Content-Type: %s; name="%s"%s',
2602:                         $type,
2603:                         $this->encodeHeader($this->secureHeader($name)),
2604:                         $this->LE
2605:                     );
2606:                 } else {
2607:                     $mime[] = sprintf(
2608:                         'Content-Type: %s%s',
2609:                         $type,
2610:                         $this->LE
2611:                     );
2612:                 }
2613:                 // RFC1341 part 5 says 7bit is assumed if not specified
2614:                 if ($encoding != '7bit') {
2615:                     $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE);
2616:                 }
2617: 
2618:                 if ($disposition == 'inline') {
2619:                     $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE);
2620:                 }
2621: 
2622:                 // If a filename contains any of these chars, it should be quoted,
2623:                 // but not otherwise: RFC2183 & RFC2045 5.1
2624:                 // Fixes a warning in IETF's msglint MIME checker
2625:                 // Allow for bypassing the Content-Disposition header totally
2626:                 if (!(empty($disposition))) {
2627:                     $encoded_name = $this->encodeHeader($this->secureHeader($name));
2628:                     if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) {
2629:                         $mime[] = sprintf(
2630:                             'Content-Disposition: %s; filename="%s"%s',
2631:                             $disposition,
2632:                             $encoded_name,
2633:                             $this->LE . $this->LE
2634:                         );
2635:                     } else {
2636:                         if (!empty($encoded_name)) {
2637:                             $mime[] = sprintf(
2638:                                 'Content-Disposition: %s; filename=%s%s',
2639:                                 $disposition,
2640:                                 $encoded_name,
2641:                                 $this->LE . $this->LE
2642:                             );
2643:                         } else {
2644:                             $mime[] = sprintf(
2645:                                 'Content-Disposition: %s%s',
2646:                                 $disposition,
2647:                                 $this->LE . $this->LE
2648:                             );
2649:                         }
2650:                     }
2651:                 } else {
2652:                     $mime[] = $this->LE;
2653:                 }
2654: 
2655:                 // Encode as string attachment
2656:                 if ($bString) {
2657:                     $mime[] = $this->encodeString($string, $encoding);
2658:                     if ($this->isError()) {
2659:                         return '';
2660:                     }
2661:                     $mime[] = $this->LE . $this->LE;
2662:                 } else {
2663:                     $mime[] = $this->encodeFile($path, $encoding);
2664:                     if ($this->isError()) {
2665:                         return '';
2666:                     }
2667:                     $mime[] = $this->LE . $this->LE;
2668:                 }
2669:             }
2670:         }
2671: 
2672:         $mime[] = sprintf('--%s--%s', $boundary, $this->LE);
2673: 
2674:         return implode('', $mime);
2675:     }
2676: 
2677:     /**
2678:      * Encode a file attachment in requested format.
2679:      * Returns an empty string on failure.
2680:      * @param string $path The full path to the file
2681:      * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
2682:      * @throws phpmailerException
2683:      * @access protected
2684:      * @return string
2685:      */
2686:     protected function encodeFile($path, $encoding = 'base64')
2687:     {
2688:         try {
2689:             if (!is_readable($path)) {
2690:                 throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
2691:             }
2692:             $magic_quotes = get_magic_quotes_runtime();
2693:             if ($magic_quotes) {
2694:                 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
2695:                     set_magic_quotes_runtime(false);
2696:                 } else {
2697:                     //Doesn't exist in PHP 5.4, but we don't need to check because
2698:                     //get_magic_quotes_runtime always returns false in 5.4+
2699:                     //so it will never get here
2700:                     ini_set('magic_quotes_runtime', false);
2701:                 }
2702:             }
2703:             $file_buffer = file_get_contents($path);
2704:             $file_buffer = $this->encodeString($file_buffer, $encoding);
2705:             if ($magic_quotes) {
2706:                 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
2707:                     set_magic_quotes_runtime($magic_quotes);
2708:                 } else {
2709:                     ini_set('magic_quotes_runtime', $magic_quotes);
2710:                 }
2711:             }
2712:             return $file_buffer;
2713:         } catch (Exception $exc) {
2714:             $this->setError($exc->getMessage());
2715:             return '';
2716:         }
2717:     }
2718: 
2719:     /**
2720:      * Encode a string in requested format.
2721:      * Returns an empty string on failure.
2722:      * @param string $str The text to encode
2723:      * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
2724:      * @access public
2725:      * @return string
2726:      */
2727:     public function encodeString($str, $encoding = 'base64')
2728:     {
2729:         $encoded = '';
2730:         switch (strtolower($encoding)) {
2731:             case 'base64':
2732:                 $encoded = chunk_split(base64_encode($str), 76, $this->LE);
2733:                 break;
2734:             case '7bit':
2735:             case '8bit':
2736:                 $encoded = $this->fixEOL($str);
2737:                 // Make sure it ends with a line break
2738:                 if (substr($encoded, -(strlen($this->LE))) != $this->LE) {
2739:                     $encoded .= $this->LE;
2740:                 }
2741:                 break;
2742:             case 'binary':
2743:                 $encoded = $str;
2744:                 break;
2745:             case 'quoted-printable':
2746:                 $encoded = $this->encodeQP($str);
2747:                 break;
2748:             default:
2749:                 $this->setError($this->lang('encoding') . $encoding);
2750:                 break;
2751:         }
2752:         return $encoded;
2753:     }
2754: 
2755:     /**
2756:      * Encode a header string optimally.
2757:      * Picks shortest of Q, B, quoted-printable or none.
2758:      * @access public
2759:      * @param string $str
2760:      * @param string $position
2761:      * @return string
2762:      */
2763:     public function encodeHeader($str, $position = 'text')
2764:     {
2765:         $matchcount = 0;
2766:         switch (strtolower($position)) {
2767:             case 'phrase':
2768:                 if (!preg_match('/[\200-\377]/', $str)) {
2769:                     // Can't use addslashes as we don't know the value of magic_quotes_sybase
2770:                     $encoded = addcslashes($str, "\0..\37\177\\\"");
2771:                     if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
2772:                         return ($encoded);
2773:                     } else {
2774:                         return ("\"$encoded\"");
2775:                     }
2776:                 }
2777:                 $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
2778:                 break;
2779:             /** @noinspection PhpMissingBreakStatementInspection */
2780:             case 'comment':
2781:                 $matchcount = preg_match_all('/[()"]/', $str, $matches);
2782:                 // Intentional fall-through
2783:             case 'text':
2784:             default:
2785:                 $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
2786:                 break;
2787:         }
2788: 
2789:         //There are no chars that need encoding
2790:         if ($matchcount == 0) {
2791:             return ($str);
2792:         }
2793: 
2794:         $maxlen = 75 - 7 - strlen($this->CharSet);
2795:         // Try to select the encoding which should produce the shortest output
2796:         if ($matchcount > strlen($str) / 3) {
2797:             // More than a third of the content will need encoding, so B encoding will be most efficient
2798:             $encoding = 'B';
2799:             if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) {
2800:                 // Use a custom function which correctly encodes and wraps long
2801:                 // multibyte strings without breaking lines within a character
2802:                 $encoded = $this->base64EncodeWrapMB($str, "\n");
2803:             } else {
2804:                 $encoded = base64_encode($str);
2805:                 $maxlen -= $maxlen % 4;
2806:                 $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
2807:             }
2808:         } else {
2809:             $encoding = 'Q';
2810:             $encoded = $this->encodeQ($str, $position);
2811:             $encoded = $this->wrapText($encoded, $maxlen, true);
2812:             $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded));
2813:         }
2814: 
2815:         $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
2816:         $encoded = trim(str_replace("\n", $this->LE, $encoded));
2817: 
2818:         return $encoded;
2819:     }
2820: 
2821:     /**
2822:      * Check if a string contains multi-byte characters.
2823:      * @access public
2824:      * @param string $str multi-byte text to wrap encode
2825:      * @return boolean
2826:      */
2827:     public function hasMultiBytes($str)
2828:     {
2829:         if (function_exists('mb_strlen')) {
2830:             return (strlen($str) > mb_strlen($str, $this->CharSet));
2831:         } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
2832:             return false;
2833:         }
2834:     }
2835: 
2836:     /**
2837:      * Does a string contain any 8-bit chars (in any charset)?
2838:      * @param string $text
2839:      * @return boolean
2840:      */
2841:     public function has8bitChars($text)
2842:     {
2843:         return (boolean)preg_match('/[\x80-\xFF]/', $text);
2844:     }
2845: 
2846:     /**
2847:      * Encode and wrap long multibyte strings for mail headers
2848:      * without breaking lines within a character.
2849:      * Adapted from a function by paravoid
2850:      * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283
2851:      * @access public
2852:      * @param string $str multi-byte text to wrap encode
2853:      * @param string $linebreak string to use as linefeed/end-of-line
2854:      * @return string
2855:      */
2856:     public function base64EncodeWrapMB($str, $linebreak = null)
2857:     {
2858:         $start = '=?' . $this->CharSet . '?B?';
2859:         $end = '?=';
2860:         $encoded = '';
2861:         if ($linebreak === null) {
2862:             $linebreak = $this->LE;
2863:         }
2864: 
2865:         $mb_length = mb_strlen($str, $this->CharSet);
2866:         // Each line must have length <= 75, including $start and $end
2867:         $length = 75 - strlen($start) - strlen($end);
2868:         // Average multi-byte ratio
2869:         $ratio = $mb_length / strlen($str);
2870:         // Base64 has a 4:3 ratio
2871:         $avgLength = floor($length * $ratio * .75);
2872: 
2873:         for ($i = 0; $i < $mb_length; $i += $offset) {
2874:             $lookBack = 0;
2875:             do {
2876:                 $offset = $avgLength - $lookBack;
2877:                 $chunk = mb_substr($str, $i, $offset, $this->CharSet);
2878:                 $chunk = base64_encode($chunk);
2879:                 $lookBack++;
2880:             } while (strlen($chunk) > $length);
2881:             $encoded .= $chunk . $linebreak;
2882:         }
2883: 
2884:         // Chomp the last linefeed
2885:         $encoded = substr($encoded, 0, -strlen($linebreak));
2886:         return $encoded;
2887:     }
2888: 
2889:     /**
2890:      * Encode a string in quoted-printable format.
2891:      * According to RFC2045 section 6.7.
2892:      * @access public
2893:      * @param string $string The text to encode
2894:      * @param integer $line_max Number of chars allowed on a line before wrapping
2895:      * @return string
2896:      * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment
2897:      */
2898:     public function encodeQP($string, $line_max = 76)
2899:     {
2900:         // Use native function if it's available (>= PHP5.3)
2901:         if (function_exists('quoted_printable_encode')) {
2902:             return quoted_printable_encode($string);
2903:         }
2904:         // Fall back to a pure PHP implementation
2905:         $string = str_replace(
2906:             array('%20', '%0D%0A.', '%0D%0A', '%'),
2907:             array(' ', "\r\n=2E", "\r\n", '='),
2908:             rawurlencode($string)
2909:         );
2910:         return preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
2911:     }
2912: 
2913:     /**
2914:      * Backward compatibility wrapper for an old QP encoding function that was removed.
2915:      * @see PHPMailer::encodeQP()
2916:      * @access public
2917:      * @param string $string
2918:      * @param integer $line_max
2919:      * @param boolean $space_conv
2920:      * @return string
2921:      * @deprecated Use encodeQP instead.
2922:      */
2923:     public function encodeQPphp(
2924:         $string,
2925:         $line_max = 76,
2926:         /** @noinspection PhpUnusedParameterInspection */ $space_conv = false
2927:     ) {
2928:         return $this->encodeQP($string, $line_max);
2929:     }
2930: 
2931:     /**
2932:      * Encode a string using Q encoding.
2933:      * @link http://tools.ietf.org/html/rfc2047
2934:      * @param string $str the text to encode
2935:      * @param string $position Where the text is going to be used, see the RFC for what that means
2936:      * @access public
2937:      * @return string
2938:      */
2939:     public function encodeQ($str, $position = 'text')
2940:     {
2941:         // There should not be any EOL in the string
2942:         $pattern = '';
2943:         $encoded = str_replace(array("\r", "\n"), '', $str);
2944:         switch (strtolower($position)) {
2945:             case 'phrase':
2946:                 // RFC 2047 section 5.3
2947:                 $pattern = '^A-Za-z0-9!*+\/ -';
2948:                 break;
2949:             /** @noinspection PhpMissingBreakStatementInspection */
2950:             case 'comment':
2951:                 // RFC 2047 section 5.2
2952:                 $pattern = '\(\)"';
2953:                 // intentional fall-through
2954:                 // for this reason we build the $pattern without including delimiters and []
2955:             case 'text':
2956:             default:
2957:                 // RFC 2047 section 5.1
2958:                 // Replace every high ascii, control, =, ? and _ characters
2959:                 $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
2960:                 break;
2961:         }
2962:         $matches = array();
2963:         if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
2964:             // If the string contains an '=', make sure it's the first thing we replace
2965:             // so as to avoid double-encoding
2966:             $eqkey = array_search('=', $matches[0]);
2967:             if (false !== $eqkey) {
2968:                 unset($matches[0][$eqkey]);
2969:                 array_unshift($matches[0], '=');
2970:             }
2971:             foreach (array_unique($matches[0]) as $char) {
2972:                 $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
2973:             }
2974:         }
2975:         // Replace every spaces to _ (more readable than =20)
2976:         return str_replace(' ', '_', $encoded);
2977:     }
2978: 
2979:     /**
2980:      * Add a string or binary attachment (non-filesystem).
2981:      * This method can be used to attach ascii or binary data,
2982:      * such as a BLOB record from a database.
2983:      * @param string $string String attachment data.
2984:      * @param string $filename Name of the attachment.
2985:      * @param string $encoding File encoding (see $Encoding).
2986:      * @param string $type File extension (MIME) type.
2987:      * @param string $disposition Disposition to use
2988:      * @return void
2989:      */
2990:     public function addStringAttachment(
2991:         $string,
2992:         $filename,
2993:         $encoding = 'base64',
2994:         $type = '',
2995:         $disposition = 'attachment'
2996:     ) {
2997:         // If a MIME type is not specified, try to work it out from the file name
2998:         if ($type == '') {
2999:             $type = self::filenameToType($filename);
3000:         }
3001:         // Append to $attachment array
3002:         $this->attachment[] = array(
3003:             0 => $string,
3004:             1 => $filename,
3005:             2 => basename($filename),
3006:             3 => $encoding,
3007:             4 => $type,
3008:             5 => true, // isStringAttachment
3009:             6 => $disposition,
3010:             7 => 0
3011:         );
3012:     }
3013: 
3014:     /**
3015:      * Add an embedded (inline) attachment from a file.
3016:      * This can include images, sounds, and just about any other document type.
3017:      * These differ from 'regular' attachments in that they are intended to be
3018:      * displayed inline with the message, not just attached for download.
3019:      * This is used in HTML messages that embed the images
3020:      * the HTML refers to using the $cid value.
3021:      * Never use a user-supplied path to a file!
3022:      * @param string $path Path to the attachment.
3023:      * @param string $cid Content ID of the attachment; Use this to reference
3024:      *        the content when using an embedded image in HTML.
3025:      * @param string $name Overrides the attachment name.
3026:      * @param string $encoding File encoding (see $Encoding).
3027:      * @param string $type File MIME type.
3028:      * @param string $disposition Disposition to use
3029:      * @return boolean True on successfully adding an attachment
3030:      */
3031:     public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
3032:     {
3033:         if (!@is_file($path)) {
3034:             $this->setError($this->lang('file_access') . $path);
3035:             return false;
3036:         }
3037: 
3038:         // If a MIME type is not specified, try to work it out from the file name
3039:         if ($type == '') {
3040:             $type = self::filenameToType($path);
3041:         }
3042: 
3043:         $filename = basename($path);
3044:         if ($name == '') {
3045:             $name = $filename;
3046:         }
3047: 
3048:         // Append to $attachment array
3049:         $this->attachment[] = array(
3050:             0 => $path,
3051:             1 => $filename,
3052:             2 => $name,
3053:             3 => $encoding,
3054:             4 => $type,
3055:             5 => false, // isStringAttachment
3056:             6 => $disposition,
3057:             7 => $cid
3058:         );
3059:         return true;
3060:     }
3061: 
3062:     /**
3063:      * Add an embedded stringified attachment.
3064:      * This can include images, sounds, and just about any other document type.
3065:      * Be sure to set the $type to an image type for images:
3066:      * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'.
3067:      * @param string $string The attachment binary data.
3068:      * @param string $cid Content ID of the attachment; Use this to reference
3069:      *        the content when using an embedded image in HTML.
3070:      * @param string $name
3071:      * @param string $encoding File encoding (see $Encoding).
3072:      * @param string $type MIME type.
3073:      * @param string $disposition Disposition to use
3074:      * @return boolean True on successfully adding an attachment
3075:      */
3076:     public function addStringEmbeddedImage(
3077:         $string,
3078:         $cid,
3079:         $name = '',
3080:         $encoding = 'base64',
3081:         $type = '',
3082:         $disposition = 'inline'
3083:     ) {
3084:         // If a MIME type is not specified, try to work it out from the name
3085:         if ($type == '' and !empty($name)) {
3086:             $type = self::filenameToType($name);
3087:         }
3088: 
3089:         // Append to $attachment array
3090:         $this->attachment[] = array(
3091:             0 => $string,
3092:             1 => $name,
3093:             2 => $name,
3094:             3 => $encoding,
3095:             4 => $type,
3096:             5 => true, // isStringAttachment
3097:             6 => $disposition,
3098:             7 => $cid
3099:         );
3100:         return true;
3101:     }
3102: 
3103:     /**
3104:      * Check if an inline attachment is present.
3105:      * @access public
3106:      * @return boolean
3107:      */
3108:     public function inlineImageExists()
3109:     {
3110:         foreach ($this->attachment as $attachment) {
3111:             if ($attachment[6] == 'inline') {
3112:                 return true;
3113:             }
3114:         }
3115:         return false;
3116:     }
3117: 
3118:     /**
3119:      * Check if an attachment (non-inline) is present.
3120:      * @return boolean
3121:      */
3122:     public function attachmentExists()
3123:     {
3124:         foreach ($this->attachment as $attachment) {
3125:             if ($attachment[6] == 'attachment') {
3126:                 return true;
3127:             }
3128:         }
3129:         return false;
3130:     }
3131: 
3132:     /**
3133:      * Check if this message has an alternative body set.
3134:      * @return boolean
3135:      */
3136:     public function alternativeExists()
3137:     {
3138:         return !empty($this->AltBody);
3139:     }
3140: 
3141:     /**
3142:      * Clear queued addresses of given kind.
3143:      * @access protected
3144:      * @param string $kind 'to', 'cc', or 'bcc'
3145:      * @return void
3146:      */
3147:     public function clearQueuedAddresses($kind)
3148:     {
3149:         $RecipientsQueue = $this->RecipientsQueue;
3150:         foreach ($RecipientsQueue as $address => $params) {
3151:             if ($params[0] == $kind) {
3152:                 unset($this->RecipientsQueue[$address]);
3153:             }
3154:         }
3155:     }
3156: 
3157:     /**
3158:      * Clear all To recipients.
3159:      * @return void
3160:      */
3161:     public function clearAddresses()
3162:     {
3163:         foreach ($this->to as $to) {
3164:             unset($this->all_recipients[strtolower($to[0])]);
3165:         }
3166:         $this->to = array();
3167:         $this->clearQueuedAddresses('to');
3168:     }
3169: 
3170:     /**
3171:      * Clear all CC recipients.
3172:      * @return void
3173:      */
3174:     public function clearCCs()
3175:     {
3176:         foreach ($this->cc as $cc) {
3177:             unset($this->all_recipients[strtolower($cc[0])]);
3178:         }
3179:         $this->cc = array();
3180:         $this->clearQueuedAddresses('cc');
3181:     }
3182: 
3183:     /**
3184:      * Clear all BCC recipients.
3185:      * @return void
3186:      */
3187:     public function clearBCCs()
3188:     {
3189:         foreach ($this->bcc as $bcc) {
3190:             unset($this->all_recipients[strtolower($bcc[0])]);
3191:         }
3192:         $this->bcc = array();
3193:         $this->clearQueuedAddresses('bcc');
3194:     }
3195: 
3196:     /**
3197:      * Clear all ReplyTo recipients.
3198:      * @return void
3199:      */
3200:     public function clearReplyTos()
3201:     {
3202:         $this->ReplyTo = array();
3203:         $this->ReplyToQueue = array();
3204:     }
3205: 
3206:     /**
3207:      * Clear all recipient types.
3208:      * @return void
3209:      */
3210:     public function clearAllRecipients()
3211:     {
3212:         $this->to = array();
3213:         $this->cc = array();
3214:         $this->bcc = array();
3215:         $this->all_recipients = array();
3216:         $this->RecipientsQueue = array();
3217:     }
3218: 
3219:     /**
3220:      * Clear all filesystem, string, and binary attachments.
3221:      * @return void
3222:      */
3223:     public function clearAttachments()
3224:     {
3225:         $this->attachment = array();
3226:     }
3227: 
3228:     /**
3229:      * Clear all custom headers.
3230:      * @return void
3231:      */
3232:     public function clearCustomHeaders()
3233:     {
3234:         $this->CustomHeader = array();
3235:     }
3236: 
3237:     /**
3238:      * Add an error message to the error container.
3239:      * @access protected
3240:      * @param string $msg
3241:      * @return void
3242:      */
3243:     protected function setError($msg)
3244:     {
3245:         $this->error_count++;
3246:         if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
3247:             $lasterror = $this->smtp->getError();
3248:             if (!empty($lasterror['error'])) {
3249:                 $msg .= $this->lang('smtp_error') . $lasterror['error'];
3250:                 if (!empty($lasterror['detail'])) {
3251:                     $msg .= ' Detail: '. $lasterror['detail'];
3252:                 }
3253:                 if (!empty($lasterror['smtp_code'])) {
3254:                     $msg .= ' SMTP code: ' . $lasterror['smtp_code'];
3255:                 }
3256:                 if (!empty($lasterror['smtp_code_ex'])) {
3257:                     $msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex'];
3258:                 }
3259:             }
3260:         }
3261:         $this->ErrorInfo = $msg;
3262:     }
3263: 
3264:     /**
3265:      * Return an RFC 822 formatted date.
3266:      * @access public
3267:      * @return string
3268:      * @static
3269:      */
3270:     public static function rfcDate()
3271:     {
3272:         // Set the time zone to whatever the default is to avoid 500 errors
3273:         // Will default to UTC if it's not set properly in php.ini
3274:         date_default_timezone_set(@date_default_timezone_get());
3275:         return date('D, j M Y H:i:s O');
3276:     }
3277: 
3278:     /**
3279:      * Get the server hostname.
3280:      * Returns 'localhost.localdomain' if unknown.
3281:      * @access protected
3282:      * @return string
3283:      */
3284:     protected function serverHostname()
3285:     {
3286:         $result = 'localhost.localdomain';
3287:         if (!empty($this->Hostname)) {
3288:             $result = $this->Hostname;
3289:         } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) {
3290:             $result = $_SERVER['SERVER_NAME'];
3291:         } elseif (function_exists('gethostname') && gethostname() !== false) {
3292:             $result = gethostname();
3293:         } elseif (php_uname('n') !== false) {
3294:             $result = php_uname('n');
3295:         }
3296:         return $result;
3297:     }
3298: 
3299:     /**
3300:      * Get an error message in the current language.
3301:      * @access protected
3302:      * @param string $key
3303:      * @return string
3304:      */
3305:     protected function lang($key)
3306:     {
3307:         if (count($this->language) < 1) {
3308:             $this->setLanguage('en'); // set the default language
3309:         }
3310: 
3311:         if (array_key_exists($key, $this->language)) {
3312:             if ($key == 'smtp_connect_failed') {
3313:                 //Include a link to troubleshooting docs on SMTP connection failure
3314:                 //this is by far the biggest cause of support questions
3315:                 //but it's usually not PHPMailer's fault.
3316:                 return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting';
3317:             }
3318:             return $this->language[$key];
3319:         } else {
3320:             //Return the key as a fallback
3321:             return $key;
3322:         }
3323:     }
3324: 
3325:     /**
3326:      * Check if an error occurred.
3327:      * @access public
3328:      * @return boolean True if an error did occur.
3329:      */
3330:     public function isError()
3331:     {
3332:         return ($this->error_count > 0);
3333:     }
3334: 
3335:     /**
3336:      * Ensure consistent line endings in a string.
3337:      * Changes every end of line from CRLF, CR or LF to $this->LE.
3338:      * @access public
3339:      * @param string $str String to fixEOL
3340:      * @return string
3341:      */
3342:     public function fixEOL($str)
3343:     {
3344:         // Normalise to \n
3345:         $nstr = str_replace(array("\r\n", "\r"), "\n", $str);
3346:         // Now convert LE as needed
3347:         if ($this->LE !== "\n") {
3348:             $nstr = str_replace("\n", $this->LE, $nstr);
3349:         }
3350:         return $nstr;
3351:     }
3352: 
3353:     /**
3354:      * Add a custom header.
3355:      * $name value can be overloaded to contain
3356:      * both header name and value (name:value)
3357:      * @access public
3358:      * @param string $name Custom header name
3359:      * @param string $value Header value
3360:      * @return void
3361:      */
3362:     public function addCustomHeader($name, $value = null)
3363:     {
3364:         if ($value === null) {
3365:             // Value passed in as name:value
3366:             $this->CustomHeader[] = explode(':', $name, 2);
3367:         } else {
3368:             $this->CustomHeader[] = array($name, $value);
3369:         }
3370:     }
3371: 
3372:     /**
3373:      * Returns all custom headers.
3374:      * @return array
3375:      */
3376:     public function getCustomHeaders()
3377:     {
3378:         return $this->CustomHeader;
3379:     }
3380: 
3381:     /**
3382:      * Create a message body from an HTML string.
3383:      * Automatically inlines images and creates a plain-text version by converting the HTML,
3384:      * overwriting any existing values in Body and AltBody.
3385:      * Do not source $message content from user input!
3386:      * $basedir is prepended when handling relative URLs, e.g. <img src="/images/a.png"> and must not be empty
3387:      * will look for an image file in $basedir/images/a.png and convert it to inline.
3388:      * If you don't provide a $basedir, relative paths will be left untouched (and thus probably break in email)
3389:      * If you don't want to apply these transformations to your HTML, just set Body and AltBody directly.
3390:      * @access public
3391:      * @param string $message HTML message string
3392:      * @param string $basedir Absolute path to a base directory to prepend to relative paths to images
3393:      * @param boolean|callable $advanced Whether to use the internal HTML to text converter
3394:      *    or your own custom converter @see PHPMailer::html2text()
3395:      * @return string $message The transformed message Body
3396:      */
3397:     public function msgHTML($message, $basedir = '', $advanced = false)
3398:     {
3399:         preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images);
3400:         if (array_key_exists(2, $images)) {
3401:             if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {
3402:                 // Ensure $basedir has a trailing /
3403:                 $basedir .= '/';
3404:             }
3405:             foreach ($images[2] as $imgindex => $url) {
3406:                 // Convert data URIs into embedded images
3407:                 if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) {
3408:                     $data = substr($url, strpos($url, ','));
3409:                     if ($match[2]) {
3410:                         $data = base64_decode($data);
3411:                     } else {
3412:                         $data = rawurldecode($data);
3413:                     }
3414:                     $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
3415:                     if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) {
3416:                         $message = str_replace(
3417:                             $images[0][$imgindex],
3418:                             $images[1][$imgindex] . '="cid:' . $cid . '"',
3419:                             $message
3420:                         );
3421:                     }
3422:                     continue;
3423:                 }
3424:                 if (
3425:                     // Only process relative URLs if a basedir is provided (i.e. no absolute local paths)
3426:                     !empty($basedir)
3427:                     // Ignore URLs containing parent dir traversal (..)
3428:                     && (strpos($url, '..') === false)
3429:                     // Do not change urls that are already inline images
3430:                     && substr($url, 0, 4) !== 'cid:'
3431:                     // Do not change absolute URLs, including anonymous protocol
3432:                     && !preg_match('#^[a-z][a-z0-9+.-]*:?//#i', $url)
3433:                 ) {
3434:                     $filename = basename($url);
3435:                     $directory = dirname($url);
3436:                     if ($directory == '.') {
3437:                         $directory = '';
3438:                     }
3439:                     $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
3440:                     if (strlen($directory) > 1 && substr($directory, -1) != '/') {
3441:                         $directory .= '/';
3442:                     }
3443:                     if ($this->addEmbeddedImage(
3444:                         $basedir . $directory . $filename,
3445:                         $cid,
3446:                         $filename,
3447:                         'base64',
3448:                         self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION))
3449:                     )
3450:                     ) {
3451:                         $message = preg_replace(
3452:                             '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui',
3453:                             $images[1][$imgindex] . '="cid:' . $cid . '"',
3454:                             $message
3455:                         );
3456:                     }
3457:                 }
3458:             }
3459:         }
3460:         $this->isHTML(true);
3461:         // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
3462:         $this->Body = $this->normalizeBreaks($message);
3463:         $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));
3464:         if (!$this->alternativeExists()) {
3465:             $this->AltBody = 'To view this email message, open it in a program that understands HTML!' .
3466:                 self::CRLF . self::CRLF;
3467:         }
3468:         return $this->Body;
3469:     }
3470: 
3471:     /**
3472:      * Convert an HTML string into plain text.
3473:      * This is used by msgHTML().
3474:      * Note - older versions of this function used a bundled advanced converter
3475:      * which was been removed for license reasons in #232.
3476:      * Example usage:
3477:      * <code>
3478:      * // Use default conversion
3479:      * $plain = $mail->html2text($html);
3480:      * // Use your own custom converter
3481:      * $plain = $mail->html2text($html, function($html) {
3482:      *     $converter = new MyHtml2text($html);
3483:      *     return $converter->get_text();
3484:      * });
3485:      * </code>
3486:      * @param string $html The HTML text to convert
3487:      * @param boolean|callable $advanced Any boolean value to use the internal converter,
3488:      *   or provide your own callable for custom conversion.
3489:      * @return string
3490:      */
3491:     public function html2text($html, $advanced = false)
3492:     {
3493:         if (is_callable($advanced)) {
3494:             return call_user_func($advanced, $html);
3495:         }
3496:         return html_entity_decode(
3497:             trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
3498:             ENT_QUOTES,
3499:             $this->CharSet
3500:         );
3501:     }
3502: 
3503:     /**
3504:      * Get the MIME type for a file extension.
3505:      * @param string $ext File extension
3506:      * @access public
3507:      * @return string MIME type of file.
3508:      * @static
3509:      */
3510:     public static function _mime_types($ext = '')
3511:     {
3512:         $mimes = array(
3513:             'xl'    => 'application/excel',
3514:             'js'    => 'application/javascript',
3515:             'hqx'   => 'application/mac-binhex40',
3516:             'cpt'   => 'application/mac-compactpro',
3517:             'bin'   => 'application/macbinary',
3518:             'doc'   => 'application/msword',
3519:             'word'  => 'application/msword',
3520:             'xlsx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
3521:             'xltx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
3522:             'potx'  => 'application/vnd.openxmlformats-officedocument.presentationml.template',
3523:             'ppsx'  => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
3524:             'pptx'  => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
3525:             'sldx'  => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
3526:             'docx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
3527:             'dotx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
3528:             'xlam'  => 'application/vnd.ms-excel.addin.macroEnabled.12',
3529:             'xlsb'  => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
3530:             'class' => 'application/octet-stream',
3531:             'dll'   => 'application/octet-stream',
3532:             'dms'   => 'application/octet-stream',
3533:             'exe'   => 'application/octet-stream',
3534:             'lha'   => 'application/octet-stream',
3535:             'lzh'   => 'application/octet-stream',
3536:             'psd'   => 'application/octet-stream',
3537:             'sea'   => 'application/octet-stream',
3538:             'so'    => 'application/octet-stream',
3539:             'oda'   => 'application/oda',
3540:             'pdf'   => 'application/pdf',
3541:             'ai'    => 'application/postscript',
3542:             'eps'   => 'application/postscript',
3543:             'ps'    => 'application/postscript',
3544:             'smi'   => 'application/smil',
3545:             'smil'  => 'application/smil',
3546:             'mif'   => 'application/vnd.mif',
3547:             'xls'   => 'application/vnd.ms-excel',
3548:             'ppt'   => 'application/vnd.ms-powerpoint',
3549:             'wbxml' => 'application/vnd.wap.wbxml',
3550:             'wmlc'  => 'application/vnd.wap.wmlc',
3551:             'dcr'   => 'application/x-director',
3552:             'dir'   => 'application/x-director',
3553:             'dxr'   => 'application/x-director',
3554:             'dvi'   => 'application/x-dvi',
3555:             'gtar'  => 'application/x-gtar',
3556:             'php3'  => 'application/x-httpd-php',
3557:             'php4'  => 'application/x-httpd-php',
3558:             'php'   => 'application/x-httpd-php',
3559:             'phtml' => 'application/x-httpd-php',
3560:             'phps'  => 'application/x-httpd-php-source',
3561:             'swf'   => 'application/x-shockwave-flash',
3562:             'sit'   => 'application/x-stuffit',
3563:             'tar'   => 'application/x-tar',
3564:             'tgz'   => 'application/x-tar',
3565:             'xht'   => 'application/xhtml+xml',
3566:             'xhtml' => 'application/xhtml+xml',
3567:             'zip'   => 'application/zip',
3568:             'mid'   => 'audio/midi',
3569:             'midi'  => 'audio/midi',
3570:             'mp2'   => 'audio/mpeg',
3571:             'mp3'   => 'audio/mpeg',
3572:             'mpga'  => 'audio/mpeg',
3573:             'aif'   => 'audio/x-aiff',
3574:             'aifc'  => 'audio/x-aiff',
3575:             'aiff'  => 'audio/x-aiff',
3576:             'ram'   => 'audio/x-pn-realaudio',
3577:             'rm'    => 'audio/x-pn-realaudio',
3578:             'rpm'   => 'audio/x-pn-realaudio-plugin',
3579:             'ra'    => 'audio/x-realaudio',
3580:             'wav'   => 'audio/x-wav',
3581:             'bmp'   => 'image/bmp',
3582:             'gif'   => 'image/gif',
3583:             'jpeg'  => 'image/jpeg',
3584:             'jpe'   => 'image/jpeg',
3585:             'jpg'   => 'image/jpeg',
3586:             'png'   => 'image/png',
3587:             'tiff'  => 'image/tiff',
3588:             'tif'   => 'image/tiff',
3589:             'eml'   => 'message/rfc822',
3590:             'css'   => 'text/css',
3591:             'html'  => 'text/html',
3592:             'htm'   => 'text/html',
3593:             'shtml' => 'text/html',
3594:             'log'   => 'text/plain',
3595:             'text'  => 'text/plain',
3596:             'txt'   => 'text/plain',
3597:             'rtx'   => 'text/richtext',
3598:             'rtf'   => 'text/rtf',
3599:             'vcf'   => 'text/vcard',
3600:             'vcard' => 'text/vcard',
3601:             'xml'   => 'text/xml',
3602:             'xsl'   => 'text/xml',
3603:             'mpeg'  => 'video/mpeg',
3604:             'mpe'   => 'video/mpeg',
3605:             'mpg'   => 'video/mpeg',
3606:             'mov'   => 'video/quicktime',
3607:             'qt'    => 'video/quicktime',
3608:             'rv'    => 'video/vnd.rn-realvideo',
3609:             'avi'   => 'video/x-msvideo',
3610:             'movie' => 'video/x-sgi-movie'
3611:         );
3612:         if (array_key_exists(strtolower($ext), $mimes)) {
3613:             return $mimes[strtolower($ext)];
3614:         }
3615:         return 'application/octet-stream';
3616:     }
3617: 
3618:     /**
3619:      * Map a file name to a MIME type.
3620:      * Defaults to 'application/octet-stream', i.e.. arbitrary binary data.
3621:      * @param string $filename A file name or full path, does not need to exist as a file
3622:      * @return string
3623:      * @static
3624:      */
3625:     public static function filenameToType($filename)
3626:     {
3627:         // In case the path is a URL, strip any query string before getting extension
3628:         $qpos = strpos($filename, '?');
3629:         if (false !== $qpos) {
3630:             $filename = substr($filename, 0, $qpos);
3631:         }
3632:         $pathinfo = self::mb_pathinfo($filename);
3633:         return self::_mime_types($pathinfo['extension']);
3634:     }
3635: 
3636:     /**
3637:      * Multi-byte-safe pathinfo replacement.
3638:      * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe.
3639:      * Works similarly to the one in PHP >= 5.2.0
3640:      * @link http://www.php.net/manual/en/function.pathinfo.php#107461
3641:      * @param string $path A filename or path, does not need to exist as a file
3642:      * @param integer|string $options Either a PATHINFO_* constant,
3643:      *      or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2
3644:      * @return string|array
3645:      * @static
3646:      */
3647:     public static function mb_pathinfo($path, $options = null)
3648:     {
3649:         $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
3650:         $pathinfo = array();
3651:         if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) {
3652:             if (array_key_exists(1, $pathinfo)) {
3653:                 $ret['dirname'] = $pathinfo[1];
3654:             }
3655:             if (array_key_exists(2, $pathinfo)) {
3656:                 $ret['basename'] = $pathinfo[2];
3657:             }
3658:             if (array_key_exists(5, $pathinfo)) {
3659:                 $ret['extension'] = $pathinfo[5];
3660:             }
3661:             if (array_key_exists(3, $pathinfo)) {
3662:                 $ret['filename'] = $pathinfo[3];
3663:             }
3664:         }
3665:         switch ($options) {
3666:             case PATHINFO_DIRNAME:
3667:             case 'dirname':
3668:                 return $ret['dirname'];
3669:             case PATHINFO_BASENAME:
3670:             case 'basename':
3671:                 return $ret['basename'];
3672:             case PATHINFO_EXTENSION:
3673:             case 'extension':
3674:                 return $ret['extension'];
3675:             case PATHINFO_FILENAME:
3676:             case 'filename':
3677:                 return $ret['filename'];
3678:             default:
3679:                 return $ret;
3680:         }
3681:     }
3682: 
3683:     /**
3684:      * Set or reset instance properties.
3685:      * You should avoid this function - it's more verbose, less efficient, more error-prone and
3686:      * harder to debug than setting properties directly.
3687:      * Usage Example:
3688:      * `$mail->set('SMTPSecure', 'tls');`
3689:      *   is the same as:
3690:      * `$mail->SMTPSecure = 'tls';`
3691:      * @access public
3692:      * @param string $name The property name to set
3693:      * @param mixed $value The value to set the property to
3694:      * @return boolean
3695:      * @TODO Should this not be using the __set() magic function?
3696:      */
3697:     public function set($name, $value = '')
3698:     {
3699:         if (property_exists($this, $name)) {
3700:             $this->$name = $value;
3701:             return true;
3702:         } else {
3703:             $this->setError($this->lang('variable_set') . $name);
3704:             return false;
3705:         }
3706:     }
3707: 
3708:     /**
3709:      * Strip newlines to prevent header injection.
3710:      * @access public
3711:      * @param string $str
3712:      * @return string
3713:      */
3714:     public function secureHeader($str)
3715:     {
3716:         return trim(str_replace(array("\r", "\n"), '', $str));
3717:     }
3718: 
3719:     /**
3720:      * Normalize line breaks in a string.
3721:      * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format.
3722:      * Defaults to CRLF (for message bodies) and preserves consecutive breaks.
3723:      * @param string $text
3724:      * @param string $breaktype What kind of line break to use, defaults to CRLF
3725:      * @return string
3726:      * @access public
3727:      * @static
3728:      */
3729:     public static function normalizeBreaks($text, $breaktype = "\r\n")
3730:     {
3731:         return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
3732:     }
3733: 
3734:     /**
3735:      * Set the public and private key files and password for S/MIME signing.
3736:      * @access public
3737:      * @param string $cert_filename
3738:      * @param string $key_filename
3739:      * @param string $key_pass Password for private key
3740:      * @param string $extracerts_filename Optional path to chain certificate
3741:      */
3742:     public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '')
3743:     {
3744:         $this->sign_cert_file = $cert_filename;
3745:         $this->sign_key_file = $key_filename;
3746:         $this->sign_key_pass = $key_pass;
3747:         $this->sign_extracerts_file = $extracerts_filename;
3748:     }
3749: 
3750:     /**
3751:      * Quoted-Printable-encode a DKIM header.
3752:      * @access public
3753:      * @param string $txt
3754:      * @return string
3755:      */
3756:     public function DKIM_QP($txt)
3757:     {
3758:         $line = '';
3759:         for ($i = 0; $i < strlen($txt); $i++) {
3760:             $ord = ord($txt[$i]);
3761:             if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
3762:                 $line .= $txt[$i];
3763:             } else {
3764:                 $line .= '=' . sprintf('%02X', $ord);
3765:             }
3766:         }
3767:         return $line;
3768:     }
3769: 
3770:     /**
3771:      * Generate a DKIM signature.
3772:      * @access public
3773:      * @param string $signHeader
3774:      * @throws phpmailerException
3775:      * @return string The DKIM signature value
3776:      */
3777:     public function DKIM_Sign($signHeader)
3778:     {
3779:         if (!defined('PKCS7_TEXT')) {
3780:             if ($this->exceptions) {
3781:                 throw new phpmailerException($this->lang('extension_missing') . 'openssl');
3782:             }
3783:             return '';
3784:         }
3785:         $privKeyStr = !empty($this->DKIM_private_string) ? $this->DKIM_private_string : file_get_contents($this->DKIM_private);
3786:         if ('' != $this->DKIM_passphrase) {
3787:             $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
3788:         } else {
3789:             $privKey = openssl_pkey_get_private($privKeyStr);
3790:         }
3791:         //Workaround for missing digest algorithms in old PHP & OpenSSL versions
3792:         //@link http://stackoverflow.com/a/11117338/333340
3793:         if (version_compare(PHP_VERSION, '5.3.0') >= 0 and
3794:             in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) {
3795:             if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
3796:                 openssl_pkey_free($privKey);
3797:                 return base64_encode($signature);
3798:             }
3799:         } else {
3800:             $pinfo = openssl_pkey_get_details($privKey);
3801:             $hash = hash('sha256', $signHeader);
3802:             //'Magic' constant for SHA256 from RFC3447
3803:             //@link https://tools.ietf.org/html/rfc3447#page-43
3804:             $t = '3031300d060960864801650304020105000420' . $hash;
3805:             $pslen = $pinfo['bits'] / 8 - (strlen($t) / 2 + 3);
3806:             $eb = pack('H*', '0001' . str_repeat('FF', $pslen) . '00' . $t);
3807: 
3808:             if (openssl_private_encrypt($eb, $signature, $privKey, OPENSSL_NO_PADDING)) {
3809:                 openssl_pkey_free($privKey);
3810:                 return base64_encode($signature);
3811:             }
3812:         }
3813:         openssl_pkey_free($privKey);
3814:         return '';
3815:     }
3816: 
3817:     /**
3818:      * Generate a DKIM canonicalization header.
3819:      * @access public
3820:      * @param string $signHeader Header
3821:      * @return string
3822:      */
3823:     public function DKIM_HeaderC($signHeader)
3824:     {
3825:         $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader);
3826:         $lines = explode("\r\n", $signHeader);
3827:         foreach ($lines as $key => $line) {
3828:             list($heading, $value) = explode(':', $line, 2);
3829:             $heading = strtolower($heading);
3830:             $value = preg_replace('/\s{2,}/', ' ', $value); // Compress useless spaces
3831:             $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value
3832:         }
3833:         $signHeader = implode("\r\n", $lines);
3834:         return $signHeader;
3835:     }
3836: 
3837:     /**
3838:      * Generate a DKIM canonicalization body.
3839:      * @access public
3840:      * @param string $body Message Body
3841:      * @return string
3842:      */
3843:     public function DKIM_BodyC($body)
3844:     {
3845:         if ($body == '') {
3846:             return "\r\n";
3847:         }
3848:         // stabilize line endings
3849:         $body = str_replace("\r\n", "\n", $body);
3850:         $body = str_replace("\n", "\r\n", $body);
3851:         // END stabilize line endings
3852:         while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
3853:             $body = substr($body, 0, strlen($body) - 2);
3854:         }
3855:         return $body;
3856:     }
3857: 
3858:     /**
3859:      * Create the DKIM header and body in a new message header.
3860:      * @access public
3861:      * @param string $headers_line Header lines
3862:      * @param string $subject Subject
3863:      * @param string $body Body
3864:      * @return string
3865:      */
3866:     public function DKIM_Add($headers_line, $subject, $body)
3867:     {
3868:         $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms
3869:         $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
3870:         $DKIMquery = 'dns/txt'; // Query method
3871:         $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
3872:         $subject_header = "Subject: $subject";
3873:         $headers = explode($this->LE, $headers_line);
3874:         $from_header = '';
3875:         $to_header = '';
3876:         $date_header = '';
3877:         $current = '';
3878:         foreach ($headers as $header) {
3879:             if (strpos($header, 'From:') === 0) {
3880:                 $from_header = $header;
3881:                 $current = 'from_header';
3882:             } elseif (strpos($header, 'To:') === 0) {
3883:                 $to_header = $header;
3884:                 $current = 'to_header';
3885:             } elseif (strpos($header, 'Date:') === 0) {
3886:                 $date_header = $header;
3887:                 $current = 'date_header';
3888:             } else {
3889:                 if (!empty($$current) && strpos($header, ' =?') === 0) {
3890:                     $$current .= $header;
3891:                 } else {
3892:                     $current = '';
3893:                 }
3894:             }
3895:         }
3896:         $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
3897:         $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
3898:         $date = str_replace('|', '=7C', $this->DKIM_QP($date_header));
3899:         $subject = str_replace(
3900:             '|',
3901:             '=7C',
3902:             $this->DKIM_QP($subject_header)
3903:         ); // Copied header fields (dkim-quoted-printable)
3904:         $body = $this->DKIM_BodyC($body);
3905:         $DKIMlen = strlen($body); // Length of body
3906:         $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
3907:         if ('' == $this->DKIM_identity) {
3908:             $ident = '';
3909:         } else {
3910:             $ident = ' i=' . $this->DKIM_identity . ';';
3911:         }
3912:         $dkimhdrs = 'DKIM-Signature: v=1; a=' .
3913:             $DKIMsignatureType . '; q=' .
3914:             $DKIMquery . '; l=' .
3915:             $DKIMlen . '; s=' .
3916:             $this->DKIM_selector .
3917:             ";\r\n" .
3918:             "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
3919:             "\th=From:To:Date:Subject;\r\n" .
3920:             "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
3921:             "\tz=$from\r\n" .
3922:             "\t|$to\r\n" .
3923:             "\t|$date\r\n" .
3924:             "\t|$subject;\r\n" .
3925:             "\tbh=" . $DKIMb64 . ";\r\n" .
3926:             "\tb=";
3927:         $toSign = $this->DKIM_HeaderC(
3928:             $from_header . "\r\n" .
3929:             $to_header . "\r\n" .
3930:             $date_header . "\r\n" .
3931:             $subject_header . "\r\n" .
3932:             $dkimhdrs
3933:         );
3934:         $signed = $this->DKIM_Sign($toSign);
3935:         return $dkimhdrs . $signed . "\r\n";
3936:     }
3937: 
3938:     /**
3939:      * Detect if a string contains a line longer than the maximum line length allowed.
3940:      * @param string $str
3941:      * @return boolean
3942:      * @static
3943:      */
3944:     public static function hasLineLongerThanMax($str)
3945:     {
3946:         //+2 to include CRLF line break for a 1000 total
3947:         return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str);
3948:     }
3949: 
3950:     /**
3951:      * Allows for public read access to 'to' property.
3952:      * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
3953:      * @access public
3954:      * @return array
3955:      */
3956:     public function getToAddresses()
3957:     {
3958:         return $this->to;
3959:     }
3960: 
3961:     /**
3962:      * Allows for public read access to 'cc' property.
3963:      * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
3964:      * @access public
3965:      * @return array
3966:      */
3967:     public function getCcAddresses()
3968:     {
3969:         return $this->cc;
3970:     }
3971: 
3972:     /**
3973:      * Allows for public read access to 'bcc' property.
3974:      * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
3975:      * @access public
3976:      * @return array
3977:      */
3978:     public function getBccAddresses()
3979:     {
3980:         return $this->bcc;
3981:     }
3982: 
3983:     /**
3984:      * Allows for public read access to 'ReplyTo' property.
3985:      * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
3986:      * @access public
3987:      * @return array
3988:      */
3989:     public function getReplyToAddresses()
3990:     {
3991:         return $this->ReplyTo;
3992:     }
3993: 
3994:     /**
3995:      * Allows for public read access to 'all_recipients' property.
3996:      * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included.
3997:      * @access public
3998:      * @return array
3999:      */
4000:     public function getAllRecipientAddresses()
4001:     {
4002:         return $this->all_recipients;
4003:     }
4004: 
4005:     /**
4006:      * Perform a callback.
4007:      * @param boolean $isSent
4008:      * @param array $to
4009:      * @param array $cc
4010:      * @param array $bcc
4011:      * @param string $subject
4012:      * @param string $body
4013:      * @param string $from
4014:      */
4015:     protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from)
4016:     {
4017:         if (!empty($this->action_function) && is_callable($this->action_function)) {
4018:             $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
4019:             call_user_func_array($this->action_function, $params);
4020:         }
4021:     }
4022: }
4023: 
4024: /**
4025:  * PHPMailer exception handler
4026:  * @package PHPMailer
4027:  */
4028: class phpmailerException extends Exception
4029: {
4030:     /**
4031:      * Prettify error message output
4032:      * @return string
4033:      */
4034:     public function errorMessage()
4035:     {
4036:         $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
4037:         return $errorMsg;
4038:     }
4039: }
4040: 
Zenphoto doc API documentation generated by ApiGen