This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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
introduced
by
![]() |
|||||
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
![]() |
|||||
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 |