1 /*************************************************************************** 2 * Copyright (c) 2024 Microsoft Corporation 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the MIT License which is available at 6 * https://opensource.org/licenses/MIT. 7 * 8 * SPDX-License-Identifier: MIT 9 **************************************************************************/ 10 11 /**************************************************************************/ 12 /**************************************************************************/ 13 /** */ 14 /** NetX SMTP Client Component */ 15 /** */ 16 /** Simple Mail Transfer Protocol (SMTP) */ 17 /** */ 18 /**************************************************************************/ 19 /**************************************************************************/ 20 21 /**************************************************************************/ 22 /* */ 23 /* APPLICATION INTERFACE DEFINITION RELEASE */ 24 /* */ 25 /* nxd_smtp_client.h PORTABLE C */ 26 /* 6.1.9 */ 27 /* AUTHOR */ 28 /* */ 29 /* Yuxin Zhou, Microsoft Corporation */ 30 /* */ 31 /* DESCRIPTION */ 32 /* */ 33 /* This file defines the NetX Simple Mail Transfer Protocol (SMTP) */ 34 /* Client component, including all data types and external references. */ 35 /* It is assumed that tx_api.h, tx_port.h, nx_api.h, and nx_port.h, */ 36 /* have already been included. */ 37 /* */ 38 /* RELEASE HISTORY */ 39 /* */ 40 /* DATE NAME DESCRIPTION */ 41 /* */ 42 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ 43 /* 09-30-2020 Yuxin Zhou Modified comment(s), */ 44 /* resulting in version 6.1 */ 45 /* 10-15-2021 Yuxin Zhou Modified comment(s), included */ 46 /* necessary header file, */ 47 /* resulting in version 6.1.9 */ 48 /* */ 49 /**************************************************************************/ 50 #ifndef NXD_SMTP_CLIENT_H 51 #define NXD_SMTP_CLIENT_H 52 53 54 /* Determine if a C++ compiler is being used. If so, ensure that standard 55 C is used to process the API information. */ 56 57 #ifdef __cplusplus 58 59 /* Yes, C++ compiler is present. Use standard C. */ 60 extern "C" { 61 62 #endif 63 64 #include "nx_api.h" 65 66 67 /* NX SMTP Client configurable options. */ 68 69 /* Set the TCP socket window size. */ 70 71 #ifndef NX_SMTP_CLIENT_TCP_WINDOW_SIZE 72 #define NX_SMTP_CLIENT_TCP_WINDOW_SIZE 1460 73 #endif 74 75 /* Set timeout on Client packet allocation in ticks. */ 76 77 #ifndef NX_SMTP_CLIENT_PACKET_TIMEOUT 78 #define NX_SMTP_CLIENT_PACKET_TIMEOUT (2 * NX_IP_PERIODIC_RATE) 79 #endif 80 81 /* Set Client TCP connection timeout in seconds. */ 82 83 #ifndef NX_SMTP_CLIENT_CONNECTION_TIMEOUT 84 #define NX_SMTP_CLIENT_CONNECTION_TIMEOUT (10 * NX_IP_PERIODIC_RATE) 85 #endif 86 87 /* Set Client TCP disconnect timeout in seconds. */ 88 89 #ifndef NX_SMTP_CLIENT_DISCONNECT_TIMEOUT 90 #define NX_SMTP_CLIENT_DISCONNECT_TIMEOUT (5 * NX_IP_PERIODIC_RATE) 91 #endif 92 93 /* Set Client timeout in seconds for waiting for server reply to client greeting. */ 94 95 #ifndef NX_SMTP_GREETING_TIMEOUT 96 #define NX_SMTP_GREETING_TIMEOUT (10 * NX_IP_PERIODIC_RATE) 97 #endif 98 99 100 /* Set Client 'envelope' timeout in seconds for waiting for server reply to client commands. */ 101 102 #ifndef NX_SMTP_ENVELOPE_TIMEOUT 103 #define NX_SMTP_ENVELOPE_TIMEOUT (10 * NX_IP_PERIODIC_RATE) 104 #endif 105 106 107 /* Set Client timeout in seconds for waiting to receive server acceptance of client message data. */ 108 109 #ifndef NX_SMTP_MESSAGE_TIMEOUT 110 #define NX_SMTP_MESSAGE_TIMEOUT (30 * NX_IP_PERIODIC_RATE) 111 #endif 112 113 114 /* Set timeout for TCP socket send completion. */ 115 116 #ifndef NX_SMTP_CLIENT_SEND_TIMEOUT 117 #define NX_SMTP_CLIENT_SEND_TIMEOUT (5 * NX_IP_PERIODIC_RATE) 118 #endif 119 120 121 /* Define size for Client profile data. */ 122 123 #ifndef NX_SMTP_CLIENT_MAX_USERNAME 124 #define NX_SMTP_CLIENT_MAX_USERNAME 40 125 #endif 126 127 #ifndef NX_SMTP_CLIENT_MAX_PASSWORD 128 #define NX_SMTP_CLIENT_MAX_PASSWORD 20 129 #endif 130 131 132 133 /* Define size of the buffer to extract the server challenge for authentication. 134 There is no specific size here so 200 bytes is sufficient to cover all digest string handling. */ 135 #ifndef NX_SMTP_SERVER_CHALLENGE_MAX_STRING 136 #define NX_SMTP_SERVER_CHALLENGE_MAX_STRING 200 137 #endif 138 139 140 /* Define size for handling data for authentication (LOGIN, PLAIN): 141 PLAIN requires rooms for authorization-id\0authentication-id\0passwd'. 142 The two bytes are for the NULL byte between the first two auth id and 143 between auth id and password. */ 144 145 #define NX_SMTP_CLIENT_AUTH_CHALLENGE_SIZE (NX_SMTP_CLIENT_MAX_USERNAME + NX_SMTP_CLIENT_MAX_USERNAME + NX_SMTP_CLIENT_MAX_PASSWORD + 2) 146 #define NX_SMTP_CLIENT_AUTH_CHALLENGE_ENCODED_SIZE (NX_SMTP_CLIENT_AUTH_CHALLENGE_SIZE * 4 / 3 + 1) 147 148 149 /* These define the states of the protocol state machine */ 150 151 #define NX_SMTP_CLIENT_STATE_AWAITING_REPLY 0xFFFFFFFF /* Session state depends on outcome of current response handler. */ 152 #define NX_SMTP_CLIENT_STATE_COMPLETED_NORMALLY 0xFFFFFFFE /* No internal errors, session completed normally. */ 153 #define NX_SMTP_CLIENT_STATE_ERROR 0xFFFFFFFD /* Internal errors e.g. TCP send or receive fails; session terminated abnormally. */ 154 155 156 #define NX_SMTP_INVALID_PARAM 0xA5 /* Invalid non pointer input in an SMTP service call */ 157 #define NX_SMTP_INTERNAL_ERROR 0xA3 /* Internal processing error */ 158 #define NX_SMTP_AUTHENTICATION_ERROR 0xA0 /* Invalid input for creating Client authentication. */ 159 #define NX_SMTP_OVERSIZE_MAIL_DATA 0xA1 /* Mail message exceeds buffer size */ 160 #define NX_SMTP_INVALID_SERVER_REPLY 0xA2 /* Unknown or invalid server reply */ 161 #define NX_SMTP_SERVER_ERROR_CODE_RECEIVED 0xA4 /* Received an SMTP Server error code */ 162 #define NX_SMTP_PACKET_ALLOCATE_ERROR 0xA6 /* Error allocating packet for SMTP message transmission */ 163 #define NX_SMTP_GREET_REPLY_ERROR 0xA7 /* Error in response to Client SMTP GREET command */ 164 #define NX_SMTP_HELLO_REPLY_ERROR 0xA8 /* Error in response to Client SMTP HELO or EHLO command */ 165 #define NX_SMTP_MAIL_REPLY_ERROR 0xA9 /* Error in response to Client SMTP MAIL command */ 166 #define NX_SMTP_RCPT_REPLY_ERROR 0xAA /* Error in response to Client SMTP RCPT command */ 167 #define NX_SMTP_MESSAGE_REPLY_ERROR 0xAB /* Error in response to Client SMTP MESSAGE data sent */ 168 #define NX_SMTP_DATA_REPLY_ERROR 0xAC /* Error in response to Client SMTP DATA command */ 169 #define NX_SMTP_AUTH_REPLY_ERROR 0xAD /* Error in response to Client SMTP AUTH command */ 170 #define NX_SMTP_SERVER_ERROR_REPLY 0xAE /* Error in parsing Server reply code (not found or unknown) */ 171 #define NX_SMTP_TRANSMIT_ERROR 0xAF /* Error occurred during TCP packet transmission e.g. send queue full */ 172 #define NX_SMTP_INVALID_SERVER_CHALLENGE 0xB0 /* Invalid server challenge (e.g. missing enclosing angle brackets). */ 173 #define NX_SMTP_OVERSIZE_SERVER_REPLY 0xB1 /* Server reply exceeds client session buffer size */ 174 #define NX_SMTP_CLIENT_NOT_INTIALIZED 0xB2 /* Client not created successfully e.g. socket create failed. Cannot transmit mail. */ 175 176 /* Basic SMTP commands supported by this NetX SMTP API. */ 177 178 #define NX_SMTP_COMMAND_EHLO "EHLO" 179 #define NX_SMTP_COMMAND_HELO "HELO" 180 #define NX_SMTP_COMMAND_MAIL "MAIL FROM" 181 #define NX_SMTP_COMMAND_RCPT "RCPT TO" 182 #define NX_SMTP_COMMAND_AUTH "AUTH" 183 #define NX_SMTP_COMMAND_NOOP "NOOP" 184 #define NX_SMTP_COMMAND_DATA "DATA" 185 #define NX_SMTP_COMMAND_RSET "RSET" 186 #define NX_SMTP_COMMAND_QUIT "QUIT" 187 188 /* List of common SMTP server reply codes */ 189 190 #define NX_SMTP_CODE_GREETING_OK 220 191 #define NX_SMTP_CODE_ACKNOWLEDGE_QUIT 221 192 #define NX_SMTP_CODE_AUTHENTICATION_SUCCESSFUL 235 193 #define NX_SMTP_CODE_OK_TO_CONTINUE 250 194 #define NX_SMTP_CODE_CANNOT_VERIFY_RECIPIENT 252 195 #define NX_SMTP_CODE_AUTHENTICATION_TYPE_ACCEPTED 334 196 #define NX_SMTP_CODE_SEND_MAIL_INPUT 354 197 #define NX_SMTP_CODE_SERVICE_NOT_AVAILABLE 421 198 #define NX_SMTP_CODE_SERVICE_INTERNAL_SERVER_ERROR 451 199 #define NX_SMTP_CODE_INSUFFICIENT_STORAGE 452 200 #define NX_SMTP_CODE_AUTH_FAILED_INTERNAL_SERVER_ERROR 454 201 #define NX_SMTP_CODE_COMMAND_SYNTAX_ERROR 500 202 #define NX_SMTP_CODE_PARAMETER_SYNTAX_ERROR 501 203 #define NX_SMTP_CODE_COMMAND_NOT_IMPLEMENTED 502 204 #define NX_SMTP_CODE_BAD_SEQUENCE 503 205 #define NX_SMTP_CODE_PARAMETER_NOT_IMPLEMENTED 504 206 #define NX_SMTP_CODE_AUTH_REQUIRED 530 207 #define NX_SMTP_CODE_AUTH_FAILED 535 208 #define NX_SMTP_CODE_REQUESTED_ACTION_NOT_TAKEN 550 209 #define NX_SMTP_CODE_USER_NOT_LOCAL 551 210 #define NX_SMTP_CODE_OVERSIZE_MAIL_DATA 552 211 #define NX_SMTP_CODE_BAD_MAILBOX 553 212 #define NX_SMTP_CODE_TRANSACTION_FAILED 554 213 #define NX_SMTP_CODE_BAD_SERVER_CODE_RECEIVED 555 214 215 216 /* Common components of SMTP command messages */ 217 218 #define NX_SMTP_LINE_TERMINATOR "\r\n" 219 #define NX_SMTP_EOM "\r\n.\r\n" 220 #define NX_SMTP_MESSAGE_ID "Message-ID" 221 #define NX_SMTP_TO_STRING "To: " 222 #define NX_SMTP_FROM_STRING "From: " 223 #define NX_SMTP_SUBJECT_STRING "Subject: " 224 #define NX_SMTP_MAIL_HEADER_COMPONENTS "MIME-Version: 1.0\r\n" \ 225 "Content-Type: text/plain;\r\n" \ 226 " charset=\"utf-8\"\r\n" \ 227 "Content-Transfer-Encoding: 8bit\r\n" \ 228 "\r\n" 229 230 231 /* Enumerated states of the protocol state machine. These MUST be in the 232 same order as the list of protocol states in NX_SMTP_CLIENT_STATES.*/ 233 234 typedef enum NX_SMTP_CLIENT_STATE_ENUM 235 { 236 NX_SMTP_CLIENT_STATE_IDLE = 0, 237 NX_SMTP_CLIENT_STATE_GREETING, /*1*/ 238 NX_SMTP_CLIENT_STATE_EHLO, /*2 */ 239 NX_SMTP_CLIENT_STATE_HELO, /*3*/ 240 NX_SMTP_CLIENT_STATE_MAIL, /*4*/ 241 NX_SMTP_CLIENT_STATE_RCPT, /*5*/ 242 NX_SMTP_CLIENT_STATE_DATA, /*6*/ 243 NX_SMTP_CLIENT_STATE_MESSAGE, /*7*/ 244 NX_SMTP_CLIENT_STATE_RSET, /*8*/ 245 NX_SMTP_CLIENT_STATE_QUIT, /*9*/ 246 NX_SMTP_CLIENT_STATE_NOOP, /*10 */ 247 NX_SMTP_CLIENT_STATE_AUTH, /*11*/ 248 NX_SMTP_CLIENT_STATE_AUTH_CHALLENGE /*12*/ 249 250 } NX_SMTP_CLIENT_STATE; 251 252 253 /* Enumeration of common server challenges to the client */ 254 255 #define NX_SMTP_CLIENT_REPLY_TO_UNKNOWN_PROMPT 1 256 #define NX_SMTP_CLIENT_REPLY_TO_USERNAME_PROMPT 2 257 #define NX_SMTP_CLIENT_REPLY_TO_PASSWORD_PROMPT 3 258 #define NX_SMTP_CLIENT_REPLY_SERVER_CHALLENGE_PROMPT 4 259 260 /* Common server challenges from the SMTP server. */ 261 262 #define NX_SMTP_USERNAME_PROMPT "Username:" 263 #define NX_SMTP_PASSWORD_PROMPT "Password:" 264 265 /* ID for identifying as an SMTP client */ 266 267 #define NX_SMTP_CLIENT_ID 0x534D5450UL 268 269 /* Define the character to cancel authentication process (RFC mandated). */ 270 271 #define NX_SMTP_CANCEL_AUTHENTICATION "*" 272 273 274 /* Enumeration of the state of authentication between server and client */ 275 276 typedef enum NX_SMTP_AUTHENTICATION_STATE_ENUM 277 { 278 NX_SMTP_NOT_AUTHENTICATED, 279 NX_SMTP_AUTHENTICATION_IN_PROGRESS, 280 NX_SMTP_AUTHENTICATION_FAILED, 281 NX_SMTP_AUTHENTICATION_SUCCEEDED 282 283 } NX_SMTP_AUTHENTICATION_STATE; 284 285 286 /* Defines for deciding priority of mail. */ 287 288 #define NX_SMTP_MAIL_PRIORITY_LOW 0x01 289 #define NX_SMTP_MAIL_PRIORITY_NORMAL 0x02 290 #define NX_SMTP_MAIL_PRIORITY_HIGH 0x04 291 292 293 /* Defines for type of mail recipient. */ 294 295 #define NX_SMTP_RECIPIENT_TO 0x01 296 #define NX_SMTP_RECIPIENT_CC 0x02 297 #define NX_SMTP_RECIPIENT_BCC 0x04 298 299 300 /* Define size of SMTP reply status codes (RFC mandated). */ 301 302 #define NX_SMTP_SERVER_REPLY_CODE_SIZE 3 303 304 #define NX_SMTP_CLIENT_AUTH_NONE 0xFFFF 305 #define NX_SMTP_CLIENT_AUTH_LOGIN 1 306 #define NX_SMTP_CLIENT_AUTH_LOGIN_TEXT "AUTH LOGIN" 307 #define NX_SMTP_CLIENT_AUTH_CRAM_MD5 2 308 #define NX_SMTP_CLIENT_AUTH_CRAM_MD5_TEXT "AUTH CRAM-MD5" 309 #define NX_SMTP_CLIENT_AUTH_PLAIN 3 310 #define NX_SMTP_CLIENT_AUTH_PLAIN_TEXT "AUTH PLAIN" 311 312 /* Define the NetX SMTP RECIPIENT structure */ 313 314 /* Define the NetX SMTP MAIL structure */ 315 316 typedef struct NX_SMTP_CLIENT_MAIL_STRUCT 317 { 318 CHAR *nx_smtp_client_mail_recipient_address; /* Recipient's mailbox address */ 319 CHAR *nx_smtp_client_mail_from_address; /* Sender's mailbox address. */ 320 UINT nx_smtp_client_mail_priority; /* Mail item priority level */ 321 CHAR *nx_smtp_client_mail_subject; 322 CHAR *nx_smtp_client_mail_body; /* Pointer to text of mail to send. */ 323 UINT nx_smtp_client_mail_body_length; /* Size of mail buffer. */ 324 } NX_SMTP_CLIENT_MAIL; 325 326 327 /* Define the SMTP client structure */ 328 329 typedef struct NX_SMTP_CLIENT_STRUCT 330 { 331 ULONG nx_smtp_client_id; /* SMTP ID for identify client service. */ 332 CHAR nx_smtp_username[NX_SMTP_CLIENT_MAX_USERNAME + 1]; /* Client name (may be used in authentication) */ 333 CHAR nx_smtp_password[NX_SMTP_CLIENT_MAX_PASSWORD + 1]; /* Client password (used in authentication) */ 334 CHAR nx_smtp_client_domain[NX_SMTP_CLIENT_MAX_USERNAME + 1]; /* Client domain of the client (and sender) */ 335 UINT nx_smtp_client_authentication_type; /* Default Client authentication. */ 336 NX_IP *nx_smtp_client_ip_ptr; /* Client IP instance */ 337 NX_PACKET_POOL *nx_smtp_client_packet_pool_ptr; /* Client packet pool for sending data packets to the server */ 338 NX_SMTP_CLIENT_MAIL nx_smtp_client_mail; /* Session mail is the collection of parameters required to create an SMTP mail message. */ 339 UINT nx_smtp_client_init_status; /* If true SMTP client successfully created and ready for transmitting mail. */ 340 NXD_ADDRESS nx_smtp_server_address; /* Server IP address (IPv4 or IPv6). */ 341 USHORT nx_smtp_server_port; /* Server port. */ 342 NX_TCP_SOCKET nx_smtp_client_socket; /* Client NetX TCP socket. */ 343 UINT nx_smtp_client_cmd_state; /* Command state of the SMTP session. */ 344 UINT nx_smtp_client_rsp_state; /* Response state of the SMTP session. */ 345 UINT nx_smtp_client_reply_code_status; /* Reply code received from SMTP server. */ 346 NX_PACKET *nx_smtp_server_packet; /* Packet containing server reply. */ 347 UINT nx_smtp_client_authentication_reply; /* Buffer holding server reply text during authentication process */ 348 NX_SMTP_AUTHENTICATION_STATE nx_smtp_client_authentication_state; /* State of the authentication process */ 349 UINT nx_smtp_client_data_transparency_bytes; /* Extra bytes allowed for data transparency processing to add to message data. */ 350 UINT nx_smtp_client_mail_status; /* Status of mail acceptance by the server */ 351 UINT nx_smtp_client_mute; /* Mute command state; client waits for another packet in same SMTP state */ 352 353 } NX_SMTP_CLIENT; 354 355 356 typedef struct NX_SMTP_CLIENT_STATES_STRUCT 357 { 358 UINT (*cmd) (NX_SMTP_CLIENT *client_ptr); 359 UINT (*rsp) (NX_SMTP_CLIENT *client_ptr); 360 361 } NX_SMTP_CLIENT_STATES; 362 363 364 #ifndef NX_SMTP_SOURCE_CODE 365 366 /* Define the system API mappings based on the error checking 367 selected by the user. */ 368 369 /* Determine if error checking is desired. If so, map API functions 370 to the appropriate error checking front-ends. Otherwise, map API 371 functions to the core functions that actually perform the work. 372 Note: error checking is enabled by default. */ 373 374 375 #ifdef NX_SMTP_DISABLE_ERROR_CHECKING 376 377 /* Services without error checking. */ 378 379 #define nxd_smtp_client_create _nxd_smtp_client_create 380 #define nx_smtp_client_delete _nx_smtp_client_delete 381 #define nx_smtp_mail_send _nx_smtp_mail_send 382 #else 383 384 /* Services with error checking. */ 385 #define nxd_smtp_client_create _nxde_smtp_client_create 386 #define nx_smtp_client_delete _nxe_smtp_client_delete 387 #define nx_smtp_mail_send _nxe_smtp_mail_send 388 389 390 #endif /* NX_SMTP_DISABLE_ERROR_CHECKING */ 391 392 393 /* Define the prototypes accessible to the application software. */ 394 UINT nxd_smtp_client_create(NX_SMTP_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *client_packet_pool_ptr, 395 CHAR *username, CHAR *password, CHAR *from_address, 396 CHAR *client_domain, UINT authentication_type, 397 NXD_ADDRESS *server_address, UINT port); 398 399 UINT nx_smtp_client_delete (NX_SMTP_CLIENT *client_ptr); 400 UINT nx_smtp_mail_send(NX_SMTP_CLIENT *client_ptr, CHAR *recipient_address, UINT priority, 401 CHAR *subject, CHAR *mail_body, UINT mail_body_length); 402 403 404 #else /* NX_SMTP_SOURCE_CODE */ 405 406 407 /* SMTP source code is being compiled, do not perform any API mapping. */ 408 409 UINT _nxd_smtp_client_create(NX_SMTP_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *client_packet_pool_ptr, 410 CHAR *username, CHAR *password, CHAR *from_address, 411 CHAR *client_domain, UINT authentication_type, 412 NXD_ADDRESS *server_address, UINT port); 413 UINT _nxde_smtp_client_create(NX_SMTP_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *client_packet_pool_ptr, 414 CHAR *username, CHAR *password, CHAR *from_address, 415 CHAR *client_domain, UINT authentication_type, 416 NXD_ADDRESS *server_address, UINT port); 417 418 UINT _nx_smtp_client_delete (NX_SMTP_CLIENT *client_ptr); 419 UINT _nxe_smtp_client_delete (NX_SMTP_CLIENT *client_ptr); 420 421 UINT _nx_smtp_mail_send(NX_SMTP_CLIENT *client_ptr, CHAR *recipient_address, UINT priority, 422 CHAR *subject, CHAR *mail_body, UINT mail_body_length); 423 424 UINT _nxe_smtp_mail_send(NX_SMTP_CLIENT *client_ptr, CHAR *recipient_address, UINT priority, 425 CHAR *subject, CHAR *mail_body, UINT mail_body_length); 426 427 428 429 430 431 #endif /* NX_SMTP_SOURCE_CODE */ 432 433 /* If a C++ compiler is being used....*/ 434 #ifdef __cplusplus 435 } 436 #endif 437 438 439 #endif /* NXD_SMTP_CLIENT_H */ 440