Issues (850)

Security Analysis    4 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection (1)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (2)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

class-getpaid-notification-email-sender.php (2 issues)

Labels
1
<?php
2
/**
3
 * Contains the notification email sending class.
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * This function is responsible for sending emails.
11
 *
12
 */
13
class GetPaid_Notification_Email_Sender {
14
15
    /**
16
	 * Whether or not we should inline CSS into the email.
17
	 */
18
	public $inline_css = true;
19
20
    /**
21
	 * The wp_mail() data.
22
	 */
23
    public $wp_mail_data = null;
24
25
    /**
26
	 * Sends a new email.
27
     *
28
     * @param string|array $to The recipients email or an array of recipient emails.
29
     * @param string $subject The email's subject.
30
     * @param string $email The email body.
31
     * @param array $attachments The email attachments.
32
     *
33
     * @return bool
34
	 */
35
	public function send( $to, $subject, $email, $attachments = array() ) {
36
37
		/*
38
		 * Allow to filter data on per-email basis.
39
		 */
40
		$data = apply_filters(
41
			'getpaid_email_data',
42
			array(
43
				'to'          => array_filter( array_unique( wpinv_parse_list( $to ) ) ),
44
				'subject'     => htmlspecialchars_decode( wp_strip_all_tags( $subject ), ENT_QUOTES ),
45
				'email'       => apply_filters( 'wpinv_mail_content', $email ),
46
				'headers'     => $this->get_headers(),
47
				'attachments' => $attachments,
48
			),
49
			$this
50
		);
51
52
        // Remove slashes.
53
        $data               = (array) wp_unslash( $data );
54
55
        // Cache it.
56
		$this->wp_mail_data = $data;
57
58
		// Attach our own hooks.
59
		$this->before_sending();
60
61
        $result = false;
62
63
        foreach ( $this->wp_mail_data['to'] as $to ) {
0 ignored issues
show
$to is overwriting one of the parameters of this function.
Loading history...
64
			$result = $this->_send( $to, $data );
65
        }
66
67
		// Remove our hooks.
68
		$this->after_sending();
69
70
		$this->wp_mail_data = null;
71
72
		return $result;
73
	}
74
75
	/**
76
	 * Does the actual sending.
77
     *
78
     * @param string $to The recipient's email.
79
     * @param array $data The email's data.
80
     * @param string $email The email body.
81
     * @param array $attachments The email attachments.
82
     *
83
     * @return bool
84
	 */
85
	protected function _send( $to, $data ) {
86
87
		// Prepare the sending function.
88
		$sending_function = apply_filters( 'getpaid_email_email_sending_function', 'wp_mail' );
89
90
		// Send the actual email.
91
		$result = call_user_func(
92
			$sending_function,
93
			$to,
94
			html_entity_decode( $data['subject'], ENT_QUOTES, get_bloginfo( 'charset' ) ),
95
			$data['email'],
96
			$data['headers'],
97
			$data['attachments']
98
		);
99
100
		if ( ! $result ) {
101
			$log_message = wp_sprintf( __( "\nTime: %1\$s\nTo: %2\$s\nSubject: %3\$s\n", 'invoicing' ), date_i18n( 'F j Y H:i:s', current_time( 'timestamp' ) ), $to, $data['subject'] );
102
			wpinv_error_log( $log_message, __( 'Email from Invoicing plugin failed to send', 'invoicing' ), __FILE__, __LINE__ );
103
		}
104
105
		return $result;
106
	}
107
108
    /**
109
	 * Retrieves email headers.
110
	 */
111
	public function get_headers() {
112
113
		$name       = $this->get_from_name();
114
		$reply_to   = $this->get_reply_to();
115
		$headers    = array( "Reply-To:$name <$reply_to>" );
116
117
		return apply_filters( 'getpaid_email_headers', $headers, $this );
118
119
	}
120
121
    /**
122
	 * Fires before an email is sent
123
	 *
124
	 * @since 1.0.0
125
	 */
126
	public function before_sending() {
127
128
        do_action( 'getpaid_before_send_email', $this );
129
		add_filter( 'wp_mail_from', array( $this, 'get_from_address' ), 1000 );
130
		add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ), 1000 );
131
		add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ), 1000 );
132
		add_filter( 'wp_mail', array( $this, 'ensure_email_content' ), 1000 );
133
134
	}
135
136
    /**
137
	 * Returns the from name.
138
	 */
139
	public function get_from_name() {
140
141
        $from_name = wpinv_get_option( 'email_from_name', get_bloginfo( 'name' ) );
142
143
		if ( empty( $from_name ) ) {
144
			$from_name = get_bloginfo( 'name' );
145
        }
146
147
		return wp_specialchars_decode( $from_name, ENT_QUOTES );
148
    }
149
150
    /**
151
	 * Returns the from email.
152
	 */
153
	public function get_from_address() {
154
155
        $from_address = wpinv_get_option( 'email_from', $this->default_from_address() );
156
157
		if ( ! is_email( $from_address ) ) {
158
			$from_address = $this->default_from_address();
159
        }
160
161
        return $from_address;
162
163
    }
164
165
    /**
166
	 * The default emails from address.
167
	 *
168
	 * Defaults to wordpress@$sitename
169
	 * Some hosts will block outgoing mail from this address if it doesn't exist,
170
	 * but there's no easy alternative. Defaulting to admin_email might appear to be
171
	 * another option, but some hosts may refuse to relay mail from an unknown domain.
172
	 *
173
	 */
174
	public function default_from_address() {
175
176
		// Get the site domain and get rid of www.
177
		$sitename = strtolower( $_SERVER['SERVER_NAME'] );
178
		if ( substr( $sitename, 0, 4 ) == 'www.' ) {
179
			$sitename = substr( $sitename, 4 );
180
		}
181
182
		$from_email = 'wordpress@' . $sitename;
183
184
		return apply_filters( 'getpaid_default_from_address', $from_email );
185
186
    }
187
188
    /**
189
	 * Get the email reply-to.
190
	 *
191
	 *
192
	 * @return string The email reply-to address.
193
	 */
194
	public function get_reply_to() {
195
196
		$reply_to = current( wpinv_parse_list( wpinv_get_admin_email() ) );
0 ignored issues
show
It seems like wpinv_get_admin_email() can also be of type false; however, parameter $list of wpinv_parse_list() does only seem to accept array|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

196
		$reply_to = current( wpinv_parse_list( /** @scrutinizer ignore-type */ wpinv_get_admin_email() ) );
Loading history...
197
198
		if ( ! is_email( $reply_to ) ) {
199
			$reply_to = get_option( 'admin_email' );
200
		}
201
202
		return $reply_to;
203
    }
204
205
    /**
206
	 * Get the email content type.
207
	 *
208
	 */
209
	public function get_content_type() {
210
		return apply_filters( 'getpaid_email_content_type', 'text/html', $this );
211
    }
212
213
    /**
214
	 * Ensures that our email messages are not messed up by template plugins.
215
	 *
216
	 * @return array wp_mail_data.
217
	 */
218
	public function ensure_email_content( $args ) {
219
		$args['message'] = $this->wp_mail_data['email'];
220
		return $args;
221
    }
222
223
    /**
224
	 * A little house keeping after an email is sent.
225
	 *
226
 	 */
227
	public function after_sending() {
228
229
        do_action( 'getpaid_after_send_email', $this->wp_mail_data );
230
		remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ), 1000 );
231
		remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ), 1000 );
232
		remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ), 1000 );
233
		remove_filter( 'wp_mail', array( $this, 'ensure_email_content' ), 1000 );
234
235
	}
236
237
}
238