├── Cfg └── Template │ └── smtp-c_cfg.h ├── Cmd ├── smtp-c_cmd.c └── smtp-c_cmd.h ├── Example └── smtp-c_send.c ├── LICENSE ├── NOTICE ├── README.rst └── Source ├── smtp-c.c └── smtp-c.h /Cfg/Template/smtp-c_cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/SMTPc 4 | * Simple Mail Transfer Protocol (client) 5 | * 6 | * Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * SMTP CLIENT CONFIGURATION FILE 21 | * 22 | * TEMPLATE 23 | * 24 | * Filename : smtp-c_cfg.h 25 | * Version : V2.01.01 26 | ********************************************************************************************************* 27 | */ 28 | 29 | #ifndef SMTPc_CFG_MODULE_PRESENT 30 | #define SMTPc_CFG_MODULE_PRESENT 31 | 32 | 33 | /* 34 | ********************************************************************************************************* 35 | * SMTPc ARGUMENT CHECK CONFIGURATION 36 | * 37 | * Note(s) : (1) Configure SMTPc_CFG_ARG_CHK_EXT_EN to enable/disable the SMTP client external argument 38 | * check feature : 39 | * 40 | * (a) When ENABLED, ALL arguments received from any port interface provided by the developer 41 | * are checked/validated. 42 | * 43 | * (b) When DISABLED, NO arguments received from any port interface provided by the developer 44 | * are checked/validated. 45 | ********************************************************************************************************* 46 | */ 47 | /* Configure external argument check feature ... */ 48 | /* See Note 1. */ 49 | #define SMTPc_CFG_ARG_CHK_EXT_EN DEF_ENABLED 50 | /* DEF_DISABLED External argument check DISABLED */ 51 | /* DEF_ENABLED External argument check ENABLED */ 52 | /* 53 | ********************************************************************************************************* 54 | * SMTPc 55 | * 56 | * Note(s) : (1) Default TCP port to use when calling SMTPc_Connect() without specifying a port 57 | * to connect to. Standard listening port for SMTP servers is 25. 58 | * 59 | * (2) Standard listening port for secure SMTP servers is 465. 60 | * 61 | * (3) Configure SMTPc_CFG_AUTH_EN to enable/disable plaintext authentication. 62 | * 63 | * (4) Configure maximum lengths for both username and password, when authentication is enabled. 64 | * 65 | * (5) Corresponds to the maximum length of the displayed name associated with a mailbox, 66 | * including '\0'. This length MUST be smaller than 600 in order to respect the same 67 | * limit. 68 | * 69 | * (6) SMTPc_CFG_MSG_SUBJECT_LEN is the maximum length of the string containing the message subject, 70 | * including '\0'. The length MUST be smaller than 900 characters in order to respect the 71 | * Internet Message Format line limit. 72 | * 73 | * (7) Maximum length of the various arrays inside the SMTPc_MSG structure. 74 | ********************************************************************************************************* 75 | */ 76 | 77 | #define SMTPc_CFG_IPPORT 25 /* Cfg SMTP server IP port (see note #1). */ 78 | #define SMTPc_CFG_IPPORT_SECURE 465 /* Cfg SMTP secure server IP port (see Note #2). */ 79 | 80 | #define SMTPc_CFG_MAX_CONN_REQ_TIMEOUT_MS 5000 /* Cfg max inactivity time (ms) on CONNECT. */ 81 | #define SMTPc_CFG_MAX_CONN_CLOSE_TIMEOUT_MS 5000 /* Cfg max inactivity time (ms) on DISCONNECT. */ 82 | 83 | /* Cfg SMTP auth mechanism (see Note #3). */ 84 | #define SMTPc_CFG_AUTH_EN DEF_DISABLED 85 | /* DEF_DISABLED PLAIN auth DISABLED */ 86 | /* DEF_ENABLED PLAIN auth ENABLED */ 87 | 88 | #define SMTPc_CFG_USERNAME_MAX_LEN 50 /* Cfg username max len (see Note #4). */ 89 | #define SMTPc_CFG_PW_MAX_LEN 10 /* Cfg pw max len (see Note #4). */ 90 | 91 | #define SMTPc_CFG_MBOX_NAME_DISP_LEN 50 /* Cfg max len of sender's name (see Note #5). */ 92 | #define SMTPc_CFG_MSG_SUBJECT_LEN 50 /* Cfg max len of msg subject (see Note #6). */ 93 | 94 | /* See Note #7. */ 95 | #define SMTPc_CFG_MSG_MAX_TO 5 /* Cfg msg max nbr of TO recipients. */ 96 | #define SMTPc_CFG_MSG_MAX_CC 5 /* Cfg msg max nbr of CC recipients. */ 97 | #define SMTPc_CFG_MSG_MAX_BCC 5 /* Cfg msg max nbr of BCC recipients. */ 98 | #define SMTPc_CFG_MSG_MAX_ATTACH 5 /* Cfg msg max nbr of msg attach. */ 99 | 100 | /* 101 | ********************************************************************************************************* 102 | * TRACING 103 | ********************************************************************************************************* 104 | */ 105 | 106 | #ifndef TRACE_LEVEL_OFF 107 | #define TRACE_LEVEL_OFF 0 108 | #endif 109 | 110 | #ifndef TRACE_LEVEL_INFO 111 | #define TRACE_LEVEL_INFO 1 112 | #endif 113 | 114 | #ifndef TRACE_LEVEL_DBG 115 | #define TRACE_LEVEL_DBG 2 116 | #endif 117 | 118 | #define SMTPc_TRACE_LEVEL TRACE_LEVEL_INFO 119 | #define SMTPc_TRACE printf 120 | 121 | #endif /* End of smtpc cfg module include. */ 122 | -------------------------------------------------------------------------------- /Cmd/smtp-c_cmd.c: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/SMTPc 4 | * Simple Mail Transfer Protocol (client) 5 | * 6 | * Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * uC/SMTPc CMD SOURCE CODE 21 | * 22 | * Filename : smtp-c_cmd.c 23 | * Version : V2.01.01 24 | ********************************************************************************************************* 25 | * Note(s) : (1) Assumes the following versions (or more recent) of software modules are included in 26 | * the project build : 27 | * 28 | * (a) uC/TCP-IP V3.03.00 29 | ********************************************************************************************************* 30 | */ 31 | 32 | 33 | /* 34 | ********************************************************************************************************* 35 | * INCLUDE FILES 36 | ********************************************************************************************************* 37 | */ 38 | 39 | #define MICRIUM_SOURCE 40 | #define SMTPc_CMD_MODULE 41 | 42 | #include "smtp-c_cmd.h" 43 | #include 44 | #include 45 | #include 46 | 47 | 48 | /* 49 | ********************************************************************************************************* 50 | * LOCAL DEFINES 51 | ********************************************************************************************************* 52 | */ 53 | 54 | #define SMTPc_CMD_HELP_1 "\r\nusage: smtp_send [options]\r\n\r\n" 55 | #define SMTPc_CMD_HELP_2 " -6, Test SMTPc using IPv6 \r\n" 56 | #define SMTPc_CMD_HELP_3 " -4, Test SMTPc using IPv4 \r\n" 57 | #define SMTPc_CMD_HELP_4 " -d, Test SMTPc using server domain name (aspmx.l.google.com)\r\n" 58 | #define SMTPc_CMD_HELP_5 " -t, Set the TO address used to send the mail\r\n" 59 | 60 | #define SMTPc_CMD_OK "OK" 61 | #define SMTPc_CMD_FAIL "FAIL " 62 | 63 | #define SMTPc_CMD_SERVER_IPV4 "192.168.0.2" 64 | #define SMTPc_CMD_SERVER_IPV6 "fe80::1234:5678:" 65 | #define SMTPc_CMD_SERVER_DOMAIN_NAME "aspmx.l.google.com" 66 | 67 | #define SMTPc_CMD_MAILBOX_FROM_NAME "Test Name From" 68 | #define SMTPc_CMD_MAILBOX_FROM_ADDR "webmaster@mail.smtptest.com" 69 | #define SMTPc_CMD_MAILBOX_TO_NAME "Test Name To" 70 | #define SMTPc_CMD_MAILBOX_TO_ADDR "testto@mail.smtptest.com" 71 | 72 | 73 | #define SMTPc_CMD_USERNAME "webmaster@mail.smtptest.com" 74 | #define SMTPc_CMD_PW "password" 75 | 76 | #define SMTPc_CMD_MSG_SUBJECT "Test" 77 | #define SMTPc_CMD_MSG "This is a test message" 78 | #define SMTPc_CMD_MAILBOX_CC_ADDR "testcc1@mail.smtptest.com" 79 | #define SMTPc_CMD_MAILBOX_CC_NAME "Test Name CC1" 80 | #define SMTPc_CMD_MAILBOX_BCC_ADDR "testbcc1@mail.smtptest.com" 81 | #define SMTPc_CMD_MAILBOX_BCC_NAME "Test Name BCC 1" 82 | 83 | #define SMTPc_CMD_PARSER_DNS ASCII_CHAR_LATIN_LOWER_D 84 | #define SMTPc_CMD_PARSER_IPv6 ASCII_CHAR_DIGIT_SIX 85 | #define SMTPc_CMD_PARSER_IPv4 ASCII_CHAR_DIGIT_FOUR 86 | #define SMTPc_CMD_ARG_PARSER_CMD_BEGIN ASCII_CHAR_HYPHEN_MINUS 87 | #define SMTPc_CMD_PARSER_TO ASCII_CHAR_LATIN_LOWER_T 88 | 89 | 90 | /* 91 | ********************************************************************************************************* 92 | * LOCAL FUNCTION PROTOTYPES 93 | ********************************************************************************************************* 94 | */ 95 | 96 | CPU_INT16S SMTPcCmd_Send (CPU_INT16U argc, 97 | CPU_CHAR *p_argv[], 98 | SHELL_OUT_FNCT out_fnct, 99 | SHELL_CMD_PARAM *p_cmd_param); 100 | 101 | CPU_INT16S SMTPcCmd_Help (CPU_INT16U argc, 102 | CPU_CHAR *p_argv[], 103 | SHELL_OUT_FNCT out_fnct, 104 | SHELL_CMD_PARAM *p_cmd_param); 105 | 106 | 107 | /* 108 | ********************************************************************************************************* 109 | * LOCAL TABLES 110 | ********************************************************************************************************* 111 | */ 112 | 113 | static SHELL_CMD SMTPc_CmdTbl[] = 114 | { 115 | {"smtp_send" , SMTPcCmd_Send}, 116 | {"smtp_help" , SMTPcCmd_Help}, 117 | {0, 0} 118 | }; 119 | 120 | 121 | /* 122 | ********************************************************************************************************* 123 | * SMTPcCmd_Init() 124 | * 125 | * Description : Add uC/SMTPc cmd stubs to uC-Shell. 126 | * 127 | * Argument(s) : p_err is a pointer to an error code which will be returned to your application: 128 | * 129 | * SMTPc_CMD_ERR_NONE No error. 130 | * 131 | * SMTPc_CMD_ERR_SHELL_INIT Command table not added to uC-Shell 132 | * 133 | * Return(s) : none. 134 | * 135 | * Caller(s) : AppTaskStart(). 136 | * 137 | * Note(s) : none. 138 | ********************************************************************************************************* 139 | */ 140 | 141 | void SMTPcCmd_Init (SMTPc_CMD_ERR *p_err) 142 | { 143 | SHELL_ERR err; 144 | 145 | 146 | Shell_CmdTblAdd("smtp", SMTPc_CmdTbl, &err); 147 | 148 | if (err == SHELL_ERR_NONE) { 149 | *p_err = SMTPc_CMD_ERR_NONE; 150 | } else { 151 | *p_err = SMTPc_CMD_ERR_SHELL_INIT; 152 | } 153 | } 154 | 155 | 156 | /* 157 | ********************************************************************************************************* 158 | * SMTPc_Cmd_Send() 159 | * 160 | * Description : Send a predefine test e-mail. 161 | * 162 | * Argument(s) : argc is a count of the arguments supplied. 163 | * 164 | * p_argv an array of pointers to the strings which are those arguments. 165 | * 166 | * out_fnct is a callback to a respond to the requester. 167 | * 168 | * p_cmd_param is a pointer to additional information to pass to the command. 169 | * 170 | * 171 | * Return(s) : The number of positive data octets transmitted, if NO errors 172 | * 173 | * SHELL_OUT_ERR, otherwise 174 | * 175 | * Caller(s) : AppTaskStart(). 176 | * 177 | * Note(s) : none. 178 | ********************************************************************************************************* 179 | */ 180 | 181 | CPU_INT16S SMTPcCmd_Send (CPU_INT16U argc, 182 | CPU_CHAR *p_argv[], 183 | SHELL_OUT_FNCT out_fnct, 184 | SHELL_CMD_PARAM *p_cmd_param) 185 | { 186 | SMTPc_ERR err; 187 | CPU_INT16S output; 188 | CPU_INT16S ret_val; 189 | CPU_CHAR *p_server_addr; 190 | CPU_CHAR *p_to_addr; 191 | CPU_INT16U error_code; 192 | CPU_CHAR reply_buf[16]; 193 | CPU_INT16U cmd_namd_len; 194 | CPU_INT08U i; 195 | SMTPc_MBOX from_mbox; 196 | SMTPc_MBOX to_mbox; 197 | SMTPc_MSG mail; 198 | 199 | 200 | p_to_addr = SMTPc_CMD_MAILBOX_TO_ADDR; 201 | p_server_addr = SMTPc_CMD_SERVER_IPV4; 202 | /* Parse Arguments. */ 203 | if (argc != 0) { 204 | for (i = 1; i < argc; i++) { 205 | if (*p_argv[i] == SMTPc_CMD_ARG_PARSER_CMD_BEGIN) { 206 | switch (*(p_argv[i] + 1)) { 207 | case SMTPc_CMD_PARSER_IPv6: 208 | p_server_addr = SMTPc_CMD_SERVER_IPV6; 209 | 210 | if (argc != i + 1) { 211 | if (*p_argv[i+1] != SMTPc_CMD_ARG_PARSER_CMD_BEGIN) { 212 | p_server_addr = p_argv[i+1]; 213 | i++; 214 | } 215 | } 216 | break; 217 | 218 | case SMTPc_CMD_PARSER_IPv4: 219 | p_server_addr = SMTPc_CMD_SERVER_IPV4; 220 | 221 | if (argc != i + 1) { 222 | if (*p_argv[i+1] != SMTPc_CMD_ARG_PARSER_CMD_BEGIN) { 223 | p_server_addr = p_argv[i+1]; 224 | i++; 225 | } 226 | } 227 | break; 228 | 229 | case SMTPc_CMD_PARSER_DNS: 230 | p_server_addr = SMTPc_CMD_SERVER_DOMAIN_NAME; 231 | 232 | if (argc != i + 1) { 233 | if (*p_argv[i+1] != SMTPc_CMD_ARG_PARSER_CMD_BEGIN) { 234 | p_server_addr = p_argv[i+1]; 235 | i++; 236 | } 237 | } 238 | break; 239 | 240 | case SMTPc_CMD_PARSER_TO: 241 | if (argc != i + 1) { 242 | if (*p_argv[i+1] != SMTPc_CMD_ARG_PARSER_CMD_BEGIN) { 243 | p_to_addr = p_argv[i+1]; 244 | i++; 245 | } else { 246 | err = SMTPc_ERR_INVALID_ADDR; 247 | goto exit_fail; 248 | } 249 | } else { 250 | err = SMTPc_ERR_INVALID_ADDR; 251 | goto exit_fail; 252 | } 253 | break; 254 | 255 | default: 256 | err = SMTPc_ERR_INVALID_ADDR; 257 | goto exit_fail; 258 | break; 259 | 260 | } 261 | } 262 | } 263 | } else { 264 | err = SMTPc_ERR_INVALID_ADDR; 265 | goto exit_fail; 266 | } 267 | 268 | /* Initialize the message obj. */ 269 | SMTPc_SetMsg (&mail, &err); 270 | if (err != SMTPc_ERR_NONE) { 271 | goto exit_fail; 272 | } 273 | /* Set Mail Envelop. */ 274 | mail.From = &from_mbox; 275 | SMTPc_SetMbox(mail.From, SMTPc_CMD_MAILBOX_FROM_NAME, SMTPc_CMD_MAILBOX_FROM_ADDR, &err); 276 | if (err != SMTPc_ERR_NONE) { 277 | goto exit_fail; 278 | } 279 | mail.ToArray[0] = &to_mbox; 280 | SMTPc_SetMbox(mail.ToArray[0], SMTPc_CMD_MAILBOX_TO_NAME, p_to_addr, &err); 281 | if (err != SMTPc_ERR_NONE) { 282 | goto exit_fail; 283 | } 284 | 285 | /* Set Mail Content. */ 286 | mail.Subject = SMTPc_CMD_MSG_SUBJECT; 287 | mail.ContentBodyMsg = SMTPc_CMD_MSG; 288 | mail.ContentBodyMsgLen = sizeof(SMTPc_CMD_MSG); 289 | 290 | /* Send Mail. */ 291 | SMTPc_SendMail( p_server_addr, 292 | 0, 293 | SMTPc_CMD_USERNAME, 294 | SMTPc_CMD_PW, 295 | DEF_NULL, 296 | &mail, 297 | &err); 298 | if (err == SMTPc_ERR_NONE) { 299 | Str_Copy(&reply_buf[0], SMTPc_CMD_OK); 300 | cmd_namd_len = Str_Len(reply_buf); 301 | } else { 302 | 303 | exit_fail: 304 | error_code = err; 305 | Str_Copy(&reply_buf[0], SMTPc_CMD_FAIL); 306 | cmd_namd_len = Str_Len(reply_buf); 307 | 308 | Str_FmtNbr_Int32U(error_code, 5, 10, ' ', DEF_YES, DEF_YES, &reply_buf[cmd_namd_len]); 309 | cmd_namd_len = Str_Len(reply_buf); 310 | } 311 | 312 | reply_buf[cmd_namd_len + 0] = '\r'; 313 | reply_buf[cmd_namd_len + 1] = '\n'; 314 | reply_buf[cmd_namd_len + 2] = '\0'; 315 | 316 | cmd_namd_len = Str_Len(reply_buf); 317 | 318 | output = out_fnct(&reply_buf[0], 319 | cmd_namd_len, 320 | p_cmd_param->pout_opt); 321 | 322 | switch (output) { 323 | case SHELL_OUT_RTN_CODE_CONN_CLOSED: 324 | case SHELL_OUT_ERR: 325 | ret_val = SHELL_EXEC_ERR; 326 | break; 327 | default: 328 | ret_val = output; 329 | } 330 | 331 | return (ret_val); 332 | } 333 | 334 | 335 | /* 336 | ********************************************************************************************************* 337 | * SMTPc_Cmd_Help() 338 | * 339 | * Description : Print SMTPc command help. 340 | * 341 | * Argument(s) : argc is a count of the arguments supplied. 342 | * 343 | * p_argv an array of pointers to the strings which are those arguments. 344 | * 345 | * out_fnct is a callback to a respond to the requester. 346 | * 347 | * p_cmd_param is a pointer to additional information to pass to the command. 348 | * 349 | * 350 | * Return(s) : The number of positive data octets transmitted, if NO errors 351 | * 352 | * SHELL_OUT_ERR, otherwise 353 | * 354 | * Caller(s) : AppTaskStart(). 355 | * 356 | * Note(s) : none. 357 | ********************************************************************************************************* 358 | */ 359 | 360 | CPU_INT16S SMTPcCmd_Help (CPU_INT16U argc, 361 | CPU_CHAR *p_argv[], 362 | SHELL_OUT_FNCT out_fnct, 363 | SHELL_CMD_PARAM *p_cmd_param) 364 | { 365 | CPU_INT16U cmd_namd_len; 366 | CPU_INT16S output; 367 | CPU_INT16S ret_val; 368 | 369 | 370 | cmd_namd_len = Str_Len(SMTPc_CMD_HELP_1); 371 | output = out_fnct(SMTPc_CMD_HELP_1, 372 | cmd_namd_len, 373 | p_cmd_param->pout_opt); 374 | 375 | cmd_namd_len = Str_Len(SMTPc_CMD_HELP_2); 376 | output = out_fnct(SMTPc_CMD_HELP_2, 377 | cmd_namd_len, 378 | p_cmd_param->pout_opt); 379 | 380 | cmd_namd_len = Str_Len(SMTPc_CMD_HELP_3); 381 | output = out_fnct(SMTPc_CMD_HELP_3, 382 | cmd_namd_len, 383 | p_cmd_param->pout_opt); 384 | 385 | cmd_namd_len = Str_Len(SMTPc_CMD_HELP_4); 386 | output = out_fnct(SMTPc_CMD_HELP_4, 387 | cmd_namd_len, 388 | p_cmd_param->pout_opt); 389 | 390 | cmd_namd_len = Str_Len(SMTPc_CMD_HELP_5); 391 | output = out_fnct(SMTPc_CMD_HELP_5, 392 | cmd_namd_len, 393 | p_cmd_param->pout_opt); 394 | 395 | switch (output) { 396 | case SHELL_OUT_RTN_CODE_CONN_CLOSED: 397 | case SHELL_OUT_ERR: 398 | ret_val = SHELL_EXEC_ERR; 399 | break; 400 | default: 401 | ret_val = output; 402 | } 403 | 404 | return (ret_val); 405 | } 406 | 407 | -------------------------------------------------------------------------------- /Cmd/smtp-c_cmd.h: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/SMTPc 4 | * Simple Mail Transfer Protocol (client) 5 | * 6 | * Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * uC/SMTPc CMD SOURCE CODE 21 | * 22 | * Filename : smtp-c_cmd.h 23 | * Version : V2.01.01 24 | ********************************************************************************************************* 25 | * Note(s) : (1) Assumes the following versions (or more recent) of software modules are included in 26 | * the project build : 27 | * 28 | * (a) uC/TCP-IP V3.03.00 29 | ********************************************************************************************************* 30 | */ 31 | 32 | 33 | /* 34 | ********************************************************************************************************* 35 | * MODULE 36 | ********************************************************************************************************* 37 | */ 38 | 39 | #ifndef SMTPc_CMD_MODULE_PRESENT 40 | #define SMTPc_CMD_MODULE_PRESENT 41 | 42 | 43 | /* 44 | ********************************************************************************************************* 45 | * INCLUDE FILES 46 | * 47 | * Note(s) : (1) The following common software files are located in the following directories : 48 | * 49 | * (a) \\lib*.* 50 | * 51 | * (b) (1) \\cpu_def.h 52 | * 53 | * (2) \\\\cpu*.* 54 | * 55 | * where 56 | * directory path for custom library software 57 | * directory path for common CPU-compiler software 58 | * directory name for specific processor (CPU) 59 | * directory name for specific compiler 60 | * 61 | * (2) 62 | * 63 | * (3) NO compiler-supplied standard library functions SHOULD be used. 64 | ********************************************************************************************************* 65 | */ 66 | 67 | #include 68 | #include 69 | 70 | #include 71 | 72 | 73 | /* 74 | ********************************************************************************************************* 75 | * EXTERNS 76 | ********************************************************************************************************* 77 | */ 78 | 79 | #ifdef SMTPc_CMD_MODULE 80 | #define SMTPc_CMD_EXT 81 | #else 82 | #define SMTPc_CMD_EXT extern 83 | #endif 84 | 85 | 86 | /* 87 | ********************************************************************************************************* 88 | * DEFAULT CONFIGURATION 89 | ********************************************************************************************************* 90 | */ 91 | 92 | 93 | /* 94 | ********************************************************************************************************* 95 | * DEFINES 96 | ********************************************************************************************************* 97 | */ 98 | 99 | 100 | /* 101 | ********************************************************************************************************* 102 | * DATA TYPES 103 | ********************************************************************************************************* 104 | */ 105 | 106 | typedef enum smtpc_test_err { 107 | SMTPc_CMD_ERR_NONE = 0, /* No errors. */ 108 | 109 | SMTPc_CMD_ERR_SHELL_INIT = 10u, /* Command table not added to uC-Shell. */ 110 | 111 | } SMTPc_CMD_ERR; 112 | 113 | 114 | /* 115 | ********************************************************************************************************* 116 | * GLOBAL VARIABLES 117 | ********************************************************************************************************* 118 | */ 119 | 120 | 121 | /* 122 | ********************************************************************************************************* 123 | * MACROS 124 | ********************************************************************************************************* 125 | */ 126 | 127 | 128 | /* 129 | ********************************************************************************************************* 130 | * FUNCTION PROTOTYPES 131 | ********************************************************************************************************* 132 | */ 133 | 134 | void SMTPcCmd_Init (SMTPc_CMD_ERR *p_err); 135 | 136 | 137 | /* 138 | ********************************************************************************************************* 139 | * CONFIGURATION ERRORS 140 | ********************************************************************************************************* 141 | */ 142 | 143 | 144 | /* 145 | ********************************************************************************************************* 146 | * MODULE END 147 | ********************************************************************************************************* 148 | */ 149 | 150 | #endif /* End of smtp-c cmd module include. */ 151 | 152 | -------------------------------------------------------------------------------- /Example/smtp-c_send.c: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * EXAMPLE CODE 4 | * 5 | * This file is provided as an example on how to use Micrium products. 6 | * 7 | * Please feel free to use any application code labeled as 'EXAMPLE CODE' in 8 | * your application products. Example code may be used as is, in whole or in 9 | * part, or may be used as a reference only. This file can be modified as 10 | * required to meet the end-product requirements. 11 | * 12 | ********************************************************************************************************* 13 | */ 14 | 15 | /* 16 | ********************************************************************************************************* 17 | * 18 | * EXAMPLE 19 | * 20 | * SMTP CLIENT 21 | 22 | * 23 | * Filename : smtp-c_send.c 24 | * Version : V2.01.01 25 | ********************************************************************************************************* 26 | * Note(s) : (1) This example show how to send an e-mail with SMTP client 27 | ********************************************************************************************************* 28 | */ 29 | 30 | 31 | /* 32 | ********************************************************************************************************* 33 | * INCLUDE FILES 34 | ********************************************************************************************************* 35 | */ 36 | 37 | #include 38 | 39 | 40 | /* 41 | ********************************************************************************************************* 42 | * LOCAL DEFINES 43 | ********************************************************************************************************* 44 | */ 45 | 46 | #define SERVER_IPV4 "192.168.0.5" 47 | #define SERVER_IPV6 "fe80::1234:5678" 48 | #define SERVER_DOMAIN_NAME "aspmx.l.google.com" 49 | 50 | #define MAILBOX_FROM_NAME "John Doe" 51 | #define MAILBOX_FROM_ADDR "john.doe@foo.bar" 52 | #define USERNAME "john.doe@foo.bar" 53 | #define PASSWORD "123" 54 | 55 | #define MAILBOX_TO_NAME_1 "Jane Doe" 56 | #define MAILBOX_TO_ADDR_1 "jane.doe@foo.bar" 57 | 58 | #define MAILBOX_TO_NAME_2 "Jonnie Doe" 59 | #define MAILBOX_TO_ADDR_2 "jonnie.doe@foo.bar" 60 | 61 | #define MAILBOX_CC_NAME "Janie Doe" 62 | #define MAILBOX_CC_ADDR "janie.doe@foo.bar" 63 | 64 | #define MAILBOX_BCC_NAME "Richard Roe" 65 | #define MAILBOX_BCC_ADDR "richard.roe@foo.bar" 66 | 67 | #define MSG_SUBJECT "Test" 68 | #define MSG "This is a test message" 69 | 70 | 71 | /* 72 | ********************************************************************************************************* 73 | * AppMailSend() 74 | * 75 | * Description : Process all the step to prepare and send an email. 76 | * 77 | * Argument(s) : none. 78 | * 79 | * Return(s) : DEF_OK, No error, message sent. 80 | * 81 | * DEF_FAIL, Otherwise. 82 | * 83 | * Caller(s) : Application. 84 | * 85 | * Note(s) : none. 86 | ********************************************************************************************************* 87 | */ 88 | 89 | CPU_BOOLEAN AppMailSend (void) 90 | { 91 | CPU_CHAR *p_server_addr; 92 | SMTPc_MBOX from_mbox; 93 | SMTPc_MBOX to_mbox1; 94 | SMTPc_MBOX to_mbox2; 95 | SMTPc_MBOX cc_mbox; 96 | SMTPc_MBOX bcc_mbox; 97 | SMTPc_MSG mail; 98 | SMTPc_ERR err; 99 | CPU_INT16U port; 100 | NET_APP_SOCK_SECURE_CFG *p_secure_cfg; 101 | 102 | 103 | p_server_addr = SERVER_IPV4; 104 | /* ------------- INITIALIZE THE MAIL OBJ -------------- */ 105 | /* Set the email object mailbox and content to Null. */ 106 | /* All fields set to Null will be ignore in the email...*/ 107 | /* ...transmission. */ 108 | SMTPc_SetMsg (&mail, &err); 109 | if (err != SMTPc_ERR_NONE) { 110 | return (DEF_FAIL); 111 | } 112 | /* ---------------- SET MAIL ENVELOP ------------------ */ 113 | /* Set all the mailbox which the email is related to. */ 114 | /* SMTPc_MSG need at least the TO and FROM mailbox... */ 115 | /* ...in order to be sent properly. */ 116 | 117 | mail.From = &from_mbox; /* Set the FROM mailbox of the e-mail. */ 118 | SMTPc_SetMbox(mail.From, MAILBOX_FROM_NAME, MAILBOX_FROM_ADDR, &err); 119 | if (err != SMTPc_ERR_NONE) { 120 | return (DEF_FAIL); 121 | } 122 | 123 | mail.ToArray[0] = &to_mbox1; /* Set the TO mailbox of the e-mail. */ 124 | SMTPc_SetMbox(mail.ToArray[0], MAILBOX_TO_NAME_1, MAILBOX_TO_ADDR_1, &err); 125 | if (err != SMTPc_ERR_NONE) { 126 | return (DEF_FAIL); 127 | } 128 | /* Set the CC mailbox of the e-mail. */ 129 | mail.CCArray[0] = &cc_mbox; 130 | SMTPc_SetMbox(mail.CCArray[0], MAILBOX_CC_NAME, MAILBOX_CC_ADDR, &err); 131 | if (err != SMTPc_ERR_NONE) { 132 | return (DEF_FAIL); 133 | } 134 | /* Set the BCC mailbox of the e-mail. */ 135 | mail.BCCArray[0] = &bcc_mbox; 136 | SMTPc_SetMbox(mail.BCCArray[0], MAILBOX_BCC_NAME, MAILBOX_BCC_ADDR, &err); 137 | if (err != SMTPc_ERR_NONE) { 138 | return (DEF_FAIL); 139 | } 140 | /* The TO,CC and BCC mailbox array allow to send... */ 141 | /* ... e-mails to multiple destination. */ 142 | mail.ToArray[1] = &to_mbox2; 143 | SMTPc_SetMbox(mail.ToArray[1], MAILBOX_TO_NAME_2, MAILBOX_TO_ADDR_2, &err); 144 | if (err != SMTPc_ERR_NONE) { 145 | return (DEF_FAIL); 146 | } 147 | 148 | /* ----------------- SET MAIL CONTENT ----------------- */ 149 | /* Set the message subject and body. */ 150 | mail.Subject = MSG_SUBJECT; 151 | mail.ContentBodyMsg = MSG; 152 | mail.ContentBodyMsgLen = sizeof(MSG); 153 | 154 | /* ---------------- SET CONN SECURITY ----------------- */ 155 | port = SMTPc_CFG_IPPORT; 156 | p_secure_cfg = DEF_NULL; 157 | 158 | /* -------------------- SEND MAIL --------------------- */ 159 | SMTPc_SendMail( p_server_addr, 160 | port, 161 | USERNAME, 162 | PASSWORD, 163 | p_secure_cfg, 164 | &mail, 165 | &err); 166 | if (err != SMTPc_ERR_NONE) { 167 | return (DEF_FAIL); 168 | } 169 | return (DEF_OK); 170 | } 171 | 172 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | ATTENTION ALL USERS OF THIS REPOSITORY: 2 | 3 | The original work found in this repository is provided by Silicon Labs under the 4 | Apache License, Version 2.0. 5 | 6 | Any third party may contribute derivative works to the original work in which 7 | modifications are clearly identified as being licensed under: 8 | 9 | (1) the Apache License, Version 2.0 or a compatible open source license; or 10 | (2) under a proprietary license with a copy of such license deposited. 11 | 12 | All posted derivative works must clearly identify which license choice has been 13 | elected. 14 | 15 | No such posted derivative works will be considered to be a “Contribution” under 16 | the Apache License, Version 2.0. 17 | 18 | SILICON LABS MAKES NO WARRANTY WITH RESPECT TO ALL POSTED THIRD PARTY CONTENT 19 | AND DISCLAIMS ALL OTHER WARRANTIES OR LIABILITIES, INCLUDING ALL WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, OWNERSHIP, 21 | NON-INFRINGEMENT, AND NON-MISAPPROPRIATION. 22 | 23 | In the event a derivative work is desired to be submitted to Silicon Labs as a 24 | “Contribution” under the Apache License, Version 2.0, a “Contributor” must give 25 | written email notice to micrium@weston-embedded.com. Unless an email response in 26 | the affirmative to accept the derivative work as a “Contribution”, such email 27 | submission should be considered to have not been incorporated into the original 28 | work. 29 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. raw:: html 2 | 3 | 4 |

5 | 6 |

7 |
8 | 9 | µC/OS is a full-featured embedded operating system originally developed by Micriµm™. In addition to the two highly popular kernels, µC/OS features support for TCP/IP, USB-Device, USB-Host, and Modbus, as well as a robust File System. 10 | 11 | Since its founding in 1999 as a private company, Micriµm and its team of engineers have offered world-class embedded software components for the most critical and demanding real-time applications. Recognized as having some of the cleanest code in the industry, with easy-to-understand documentation, the Micrium real-time kernels, and software components have successfully been deployed in thousands of products worldwide across a broad range of industries. Micrium’s µC/OS-II™ kernel has been certified for use in safety-critical applications and remains a respected favorite in the medical, aerospace, and industrial markets. µC/OS continues to be the RTOS of choice for engineers requiring the most reliable and trusted solution for their mission-critical applications. 12 | 13 | ---------- 14 | 15 | .. raw:: HTML 16 | 17 | 18 |

19 | 20 |

21 |
22 | 23 | Founded by a team of former Micrium employees, Weston Embedded Solutions is the official custodian for the µC/OS RTOS and Stacks software repository to ensure it remains the trusted choice for embedded engineers around the world. 24 | 25 | ---------- 26 | 27 | Product Documentation and Release Notes 28 | *************** 29 | https://micrium.atlassian.net/ 30 | 31 | Technical Support 32 | ***************** 33 | https://weston-embedded.com/micrium-support 34 | 35 | Example Projects 36 | ********* 37 | https://weston-embedded.com/micrium-examples 38 | 39 | Commercial Licensing Option 40 | ********* 41 | https://weston-embedded.com/products/cesium 42 | 43 | Who to Contact 44 | ********* 45 | https://weston-embedded.com/company/contact -------------------------------------------------------------------------------- /Source/smtp-c.c: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/SMTPc 4 | * Simple Mail Transfer Protocol (client) 5 | * 6 | * Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * SMTP CLIENT 21 | * 22 | * Filename : smtp-c.c 23 | * Version : V2.01.01 24 | ********************************************************************************************************* 25 | * Note(s) : (1) This code implements a subset of the SMTP protocol (RFC 2821). More precisely, the 26 | * following commands have been implemented: 27 | * 28 | * HELO 29 | * AUTH (if enabled) 30 | * MAIL 31 | * RCPT 32 | * DATA 33 | * RSET 34 | * NOOP 35 | * QUIT 36 | ********************************************************************************************************* 37 | */ 38 | 39 | /* 40 | ********************************************************************************************************* 41 | * INCLUDE FILES 42 | ********************************************************************************************************* 43 | */ 44 | 45 | #define MICRIUM_SOURCE 46 | #define SMTPc_MODULE 47 | #include "smtp-c.h" 48 | 49 | 50 | /* 51 | ********************************************************************************************************* 52 | * LOCAL DEFINES 53 | ********************************************************************************************************* 54 | */ 55 | 56 | 57 | /* 58 | ********************************************************************************************************* 59 | * LOCAL CONSTANTS 60 | ********************************************************************************************************* 61 | */ 62 | 63 | 64 | /* 65 | ********************************************************************************************************* 66 | * LOCAL DATA TYPES 67 | ********************************************************************************************************* 68 | */ 69 | 70 | 71 | /* 72 | ********************************************************************************************************* 73 | * LOCAL TABLES 74 | ********************************************************************************************************* 75 | */ 76 | 77 | 78 | /* 79 | ********************************************************************************************************* 80 | * LOCAL DATA TYPES 81 | ********************************************************************************************************* 82 | */ 83 | 84 | 85 | /* 86 | ********************************************************************************************************* 87 | * LOCAL GLOBAL VARIABLES 88 | ********************************************************************************************************* 89 | */ 90 | 91 | 92 | /* 93 | ********************************************************************************************************* 94 | * FUNCTION PROTOTYPES 95 | ********************************************************************************************************* 96 | */ 97 | 98 | /* --------------------- RX FNCT'S -------------------- */ 99 | static CPU_CHAR *SMTPc_RxReply (NET_SOCK_ID sock_id, 100 | SMTPc_ERR *perr); 101 | 102 | static void SMTPc_ParseReply (CPU_CHAR *server_reply, 103 | CPU_INT32U *completion_code, 104 | SMTPc_ERR *perr); 105 | 106 | /* --------------------- TX FNCT'S -------------------- */ 107 | static void SMTPc_SendBody (NET_SOCK_ID sock_id, 108 | SMTPc_MSG *msg, 109 | SMTPc_ERR *perr); 110 | 111 | static void SMTPc_QueryServer (NET_SOCK_ID sock_id, 112 | CPU_CHAR *query, 113 | CPU_INT32U len, 114 | SMTPc_ERR *perr); 115 | 116 | /* ------------------- UTIL FNCT'S ------------------- */ 117 | static CPU_INT32U SMTPc_BuildHdr (NET_SOCK_ID sock_id, 118 | CPU_CHAR *buf, 119 | CPU_INT32U buf_size, 120 | CPU_INT32U buf_wr_ix, 121 | CPU_CHAR *hdr, 122 | CPU_CHAR *val, 123 | CPU_INT32U *line_len, 124 | SMTPc_ERR *perr); 125 | 126 | /* -------------------- CMD FNCT'S ------------------- */ 127 | static CPU_CHAR *SMTPc_HELO (NET_SOCK_ID sock_id, 128 | CPU_INT32U *completion_code, 129 | SMTPc_ERR *perr); 130 | 131 | #if (SMTPc_CFG_AUTH_EN == DEF_ENABLED) 132 | static CPU_CHAR *SMTPc_AUTH (NET_SOCK_ID sock_id, 133 | CPU_CHAR *username, 134 | CPU_CHAR *pw, 135 | CPU_INT32U *completion_code, 136 | SMTPc_ERR *perr); 137 | #endif 138 | 139 | static CPU_CHAR *SMTPc_MAIL (NET_SOCK_ID sock_id, 140 | CPU_CHAR *from, 141 | CPU_INT32U *completion_code, 142 | SMTPc_ERR *perr); 143 | 144 | static CPU_CHAR *SMTPc_RCPT (NET_SOCK_ID sock_id, 145 | CPU_CHAR *to, 146 | CPU_INT32U *completion_code, 147 | SMTPc_ERR *perr); 148 | 149 | static CPU_CHAR *SMTPc_DATA (NET_SOCK_ID sock_id, 150 | CPU_INT32U *completion_code, 151 | SMTPc_ERR *perr); 152 | 153 | static CPU_CHAR *SMTPc_RSET (NET_SOCK_ID sock_id, 154 | CPU_INT32U *completion_code, 155 | SMTPc_ERR *perr); 156 | 157 | static CPU_CHAR *SMTPc_QUIT (NET_SOCK_ID sock_id, 158 | CPU_INT32U *completion_code, 159 | SMTPc_ERR *perr); 160 | 161 | 162 | /* 163 | ********************************************************************************************************* 164 | * SMTPc_Connect() 165 | * 166 | * Description : (1) Establish a TCP connection to the SMTP server and initiate the SMTP session. 167 | * 168 | * (a) Determine port 169 | * (b) Open the socket 170 | * (c) Receive server's reply & validate 171 | * (d) Initiate SMTP session 172 | * (e) Authenticate client, if applicable 173 | * 174 | * 175 | * Argument(s) : p_host_name Pointer to host name of the SMTP server to contact. Can be also an IP address. 176 | * 177 | * port TCP port to use, or '0' if SMTPc_DFLT_PORT. 178 | * 179 | * p_username Pointer to user name, if authentication enabled. 180 | * 181 | * p_pwd Pointer to password, if authentication enabled. 182 | * 183 | * p_secure_cfg Pointer to the secure configuration (TLS/SSL): 184 | * 185 | * DEF_NULL, if no security enabled. 186 | * Pointer to a structure that contains the parameters. 187 | * 188 | * p_err Pointer to variable that will hold the return error code from this 189 | * function : 190 | * 191 | * SMTPc_ERR_NONE No error, TCP connection established. 192 | * SMTPc_ERR_NULL_ARG Argument 'username'/'pw' passed a NULL pointer. 193 | * SMTPc_ERR_SOCK_OPEN_FAILED Error opening socket. 194 | * SMTPc_ERR_SOCK_CONN_FAILED Error connecting to server. 195 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 196 | * SMTPc_ERR_REP Error with reply. 197 | * SMTPc_ERR_SECURE_NOT_AVAIL No secure mode available. 198 | * 199 | * -------- RETURNED BY SMTPc_AUTH : -------- 200 | * SMTPc_ERR_ENCODE Error encoding credentials. 201 | * SMTPc_ERR_AUTH_FAILED Error authenticating user. 202 | * 203 | * 204 | * Return(s) : Socket descriptor/handle identifier, if NO error. 205 | * 206 | * -1, otherwise. 207 | * 208 | * Caller(s) : Application. 209 | * 210 | * Note(s) : (2) Network security manager MUST be available & enabled to initialize the server in 211 | * secure mode. 212 | * 213 | * (3) If anything goes wrong while trying to connect to the server, the socket is 214 | * closed by calling NetSock_Close. Hence, all data structures are returned to 215 | * their original state in case of a failure to establish the TCP connection. 216 | * 217 | * If the failure occurs when initiating the session, the application is responsible 218 | * of the appropriate action(s) to be taken. 219 | * 220 | * (4) If authentication is disabled (SMTPc_CFG_AUTH_EN set to DEF_ENABLED), the 'p_username' 221 | * and 'p_pwd' parameters should be passed a NULL pointer. 222 | * 223 | * (5) The server will send a 220 "Service ready" reply when the connection is completed. 224 | * The SMTP protocol allows a server to formally reject a transaction while still 225 | * allowing the initial connection by responding with a 554 "Transaction failed" 226 | * reply. 227 | * 228 | * (6) The Plain-text (PLAIN) authentication mechanism is implemented here. However, it 229 | * takes some liberties from RFC #4964, section 4 'The AUTH Command', stating the "A 230 | * server implementation MUST implement a configuration in which it does not permit 231 | * any plaintext password mechanisms, unless either the STARTTLS command has been 232 | * negotiated or some other mechanism that protects the session from password snooping 233 | * has been provided". 234 | * 235 | * Since this client does not support SSL or TLS, or any other protection against 236 | * password snooping, it relies on the server NOT to fully follow RFC #4954 in order 237 | * to be successful. 238 | ********************************************************************************************************* 239 | */ 240 | 241 | NET_SOCK_ID SMTPc_Connect (CPU_CHAR *p_host_name, 242 | CPU_INT16U port, 243 | CPU_CHAR *p_username, 244 | CPU_CHAR *p_pwd, 245 | NET_APP_SOCK_SECURE_CFG *p_secure_cfg, 246 | SMTPc_ERR *p_err) 247 | { 248 | NET_SOCK_ID sock_id; 249 | CPU_INT32U completion_code; 250 | CPU_CHAR *reply; 251 | NET_ERR err_net; 252 | NET_SOCK_ADDR socket_addr; 253 | CPU_INT16U port_server; 254 | 255 | /* ------------------ VALIDATE PTR -------------------- */ 256 | #if (SMTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) 257 | #if (SMTPc_CFG_AUTH_EN == DEF_ENABLED) 258 | if ((p_username == (CPU_CHAR *)0) || 259 | (p_pwd == (CPU_CHAR *)0)) { 260 | *p_err = SMTPc_ERR_NULL_ARG; 261 | return (NET_SOCK_ID_NONE); 262 | } 263 | #else 264 | (void)&p_username; /* Prevent 'variable unused' compiler warnings. */ 265 | (void)&p_pwd; 266 | #endif 267 | 268 | #ifndef NET_SECURE_MODULE_EN /* See Note #2. */ 269 | if (p_secure_cfg != DEF_NULL) { 270 | *p_err = SMTPc_ERR_SECURE_NOT_AVAIL; 271 | return NET_SOCK_ID_NONE; 272 | } 273 | #endif 274 | 275 | #endif 276 | /* ------------------ DETERMINE PORT ------------------ */ 277 | if (port != 0) { 278 | port_server = port; 279 | } else { 280 | if (p_secure_cfg != DEF_NULL) { /* Set the port according to the secure mode cfg. */ 281 | port_server = SMTPc_CFG_IPPORT_SECURE; 282 | } else { 283 | port_server = SMTPc_CFG_IPPORT; 284 | } 285 | } 286 | /* ----------------- OPEN CLIENT STREAM --------------- */ 287 | NetApp_ClientStreamOpenByHostname(&sock_id, 288 | p_host_name, 289 | port_server, 290 | &socket_addr, 291 | p_secure_cfg, 292 | SMTPc_CFG_MAX_CONN_REQ_TIMEOUT_MS, 293 | &err_net); 294 | if ( err_net != NET_APP_ERR_NONE) { 295 | *p_err = SMTPc_ERR_SOCK_CONN_FAILED; 296 | return NET_SOCK_ID_NONE; 297 | } 298 | /* ---------------- CFG SOCK BLOCK OPT ---------------- */ 299 | (void)NetSock_CfgBlock(sock_id, NET_SOCK_BLOCK_SEL_BLOCK, &err_net); 300 | if (err_net != NET_SOCK_ERR_NONE) { 301 | NetApp_SockClose(sock_id, 302 | SMTPc_CFG_MAX_CONN_CLOSE_TIMEOUT_MS, 303 | &err_net); 304 | *p_err = SMTPc_ERR_SOCK_CONN_FAILED; 305 | return NET_SOCK_ID_NONE; 306 | } 307 | 308 | 309 | 310 | /* ---------- RX SERVER'S RESPONSE & VALIDATE --------- */ 311 | reply = SMTPc_RxReply(sock_id, p_err); /* See Note #5. */ 312 | if (*p_err != SMTPc_ERR_NONE) { 313 | NetApp_SockClose(sock_id, 314 | SMTPc_CFG_MAX_CONN_CLOSE_TIMEOUT_MS, 315 | &err_net); 316 | *p_err = SMTPc_ERR_RX_FAILED; 317 | return NET_SOCK_ID_NONE; 318 | } 319 | 320 | SMTPc_ParseReply(reply, &completion_code, p_err); 321 | switch (*p_err) { 322 | case SMTPc_ERR_REP_POS: /* If any pos rep... */ 323 | *p_err = SMTPc_ERR_NONE; /* ... no err. */ 324 | break; 325 | 326 | case SMTPc_ERR_REP_INTER: 327 | case SMTPc_ERR_REP_NEG: 328 | case SMTPc_ERR_REP_TOO_SHORT: 329 | default: 330 | NetApp_SockClose(sock_id, 331 | SMTPc_CFG_MAX_CONN_CLOSE_TIMEOUT_MS, 332 | &err_net); 333 | *p_err = SMTPc_ERR_REP; 334 | return NET_SOCK_ID_NONE; 335 | } 336 | /* -------------- INITIATE SMTP SESSION --------------- */ 337 | reply = SMTPc_HELO(sock_id, &completion_code, p_err); 338 | if (*p_err != SMTPc_ERR_NONE) { 339 | SMTPc_Disconnect(sock_id, p_err); 340 | return NET_SOCK_ID_NONE;; 341 | } 342 | 343 | /* -------------------- AUTH CLIENT ------------------- */ 344 | /* See Note #6. */ 345 | #if (SMTPc_CFG_AUTH_EN == DEF_ENABLED) 346 | SMTPc_AUTH((NET_SOCK_ID ) sock_id, 347 | (CPU_CHAR *) p_username, 348 | (CPU_CHAR *) p_pwd, 349 | (CPU_INT32U *)&completion_code, 350 | (SMTPc_ERR *) p_err); 351 | if (*p_err != SMTPc_ERR_NONE) { 352 | SMTPc_Disconnect(sock_id, p_err); 353 | return NET_SOCK_ID_NONE;; 354 | } 355 | #endif 356 | 357 | return (sock_id); 358 | } 359 | 360 | 361 | /* 362 | ********************************************************************************************************* 363 | * SMTPc_SendMsg() 364 | * 365 | * Description : (1) Send a message (an instance of the SMTPc_MSG structure) to the SMTP server. 366 | * 367 | * (a) Invoke the MAIL command 368 | * (b) Invoke the RCPT command for every recipient 369 | * (c) Invoke the DATA command 370 | * (d) Build and send the actual data 371 | * 372 | * 373 | * Argument(s) : sock_id Socket ID. 374 | * p_msg SMTPc_MSG structure encapsulating the message to send. 375 | * p_err Pointer to variable that will hold the return error code from this 376 | * function : 377 | * 378 | * SMTPc_ERR_NONE No error. 379 | * SMTPc_ERR_NULL_ARG Argument 'p_msg' passed a NULL pointer. 380 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 381 | * SMTPc_ERR_REP Error with reply. 382 | * 383 | * ------- RETURNED BY SMTPc_MAIL() : ------- 384 | * ------- RETURNED BY SMTPc_RCPT() : ------- 385 | * ------- RETURNED BY SMTPc_DATA() : ------- 386 | * SMTPc_ERR_TX_FAILED Error querying server. 387 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 388 | * SMTPc_ERR_REP Error with reply. 389 | * 390 | * ----- RETURNED BY SMTPc_SendBody() : ----- 391 | * SMTPc_ERR_TX_FAILED Error querying server. 392 | * SMTPc_ERR_LINE_TOO_LONG Line limit exceeded. 393 | * 394 | * Return(s) : none. 395 | * 396 | * Caller(s) : Application. 397 | * 398 | * Note(s) : (2) The function SMTPc_SetMsg has to be called before being able to send a message. 399 | * 400 | * (3) The message has to have at least one receiver, either "To", "CC", or "BCC". 401 | ********************************************************************************************************* 402 | */ 403 | 404 | void SMTPc_SendMsg (NET_SOCK_ID sock_id, 405 | SMTPc_MSG *p_msg, 406 | SMTPc_ERR *p_err) 407 | { 408 | CPU_INT08U i; 409 | CPU_INT32U completion_code; 410 | 411 | 412 | /* See Note #2. */ 413 | if (p_msg->From == (SMTPc_MBOX *)0) { 414 | SMTPc_TRACE_DBG(("Error SMTPc_SendMsg. NULL from parameter\n\r")); 415 | *p_err = SMTPc_ERR_NULL_ARG; 416 | return; 417 | } 418 | 419 | /* See Note #3. */ 420 | if ((p_msg->ToArray[0] == (SMTPc_MBOX *)0) && 421 | (p_msg->CCArray[0] == (SMTPc_MBOX *)0) && 422 | (p_msg->BCCArray[0] == (SMTPc_MBOX *)0)) { 423 | SMTPc_TRACE_DBG(("Error SMTPc_SendMsg. NULL parameter(s)\n\r")); 424 | *p_err = SMTPc_ERR_NULL_ARG; 425 | return; 426 | } 427 | 428 | /* --------------- INVOKE THE MAIL CMD ---------------- */ 429 | SMTPc_MAIL(sock_id, p_msg->From->Addr, &completion_code, p_err); 430 | if (*p_err != SMTPc_ERR_NONE) { 431 | SMTPc_TRACE_DBG(("Error MAIL. Code: %u\n\r", (unsigned int)completion_code)); 432 | if ((completion_code != SMTPc_REP_421) && 433 | (completion_code != SMTPc_REP_221)) { 434 | SMTPc_RSET(sock_id, &completion_code, p_err); 435 | } 436 | return; 437 | } 438 | 439 | /* --------------- INVOKE THE RCTP CMD ---------------- */ 440 | /* The RCPT cmd is tx'd for every recipient, */ 441 | /* including CCs & BCCs. */ 442 | for (i = 0; i < SMTPc_CFG_MSG_MAX_TO; i++) { 443 | if (p_msg->ToArray[i] == (SMTPc_MBOX *)0) { 444 | break; 445 | } 446 | 447 | SMTPc_RCPT(sock_id, p_msg->ToArray[i]->Addr, &completion_code, p_err); 448 | if (*p_err != SMTPc_ERR_NONE) { 449 | SMTPc_TRACE_DBG(("Error RCPT (TO %u). Code: %u\n\r", (unsigned int)i, (unsigned int)completion_code)); 450 | SMTPc_RSET(sock_id, &completion_code, p_err); /* RSET p_msg if invalid RCPT fails. */ 451 | return; 452 | } 453 | } 454 | 455 | /* CCs */ 456 | for (i = 0; i < SMTPc_CFG_MSG_MAX_CC; i++) { 457 | if (p_msg->CCArray[i] == (SMTPc_MBOX *)0) { 458 | break; 459 | } 460 | SMTPc_RCPT(sock_id, p_msg->CCArray[i]->Addr, &completion_code, p_err); 461 | if (*p_err != SMTPc_ERR_NONE) { 462 | SMTPc_TRACE_DBG(("Error RCPT (CC %u). Code: %u\n\r", (unsigned int)i, (unsigned int)completion_code)); 463 | if ((completion_code != SMTPc_REP_421) && 464 | (completion_code != SMTPc_REP_221)) { 465 | SMTPc_RSET(sock_id, &completion_code, p_err); /* RSET p_msg if invalid RCPT fails. */ 466 | } 467 | return; 468 | } 469 | } 470 | 471 | /* BCCs */ 472 | for (i = 0; i < SMTPc_CFG_MSG_MAX_BCC; i++) { 473 | if (p_msg->BCCArray[i] == (SMTPc_MBOX *)0) { 474 | break; 475 | } 476 | 477 | SMTPc_RCPT(sock_id, p_msg->BCCArray[i]->Addr, &completion_code, p_err); 478 | if (*p_err != SMTPc_ERR_NONE) { 479 | SMTPc_TRACE_DBG(("Error RCPT (BCC %u). Code: %u\n\r", (unsigned int)i, (unsigned int)completion_code)); 480 | if ((completion_code != SMTPc_REP_421) && /* RSET p_msg if invalid RCPT fails. */ 481 | (completion_code != SMTPc_REP_221)) { 482 | SMTPc_RSET(sock_id, &completion_code, p_err); 483 | } 484 | return; 485 | } 486 | } 487 | 488 | /* --------------- INVOKE THE DATA CMD ---------------- */ 489 | SMTPc_DATA(sock_id, &completion_code, p_err); 490 | if (*p_err != SMTPc_ERR_NONE) { 491 | SMTPc_TRACE_DBG(("Error DATA. Code: %u\n\r", (unsigned int)completion_code)); 492 | if ((completion_code != SMTPc_REP_421) && 493 | (completion_code != SMTPc_REP_221)) { 494 | SMTPc_RSET(sock_id, &completion_code, p_err); 495 | } 496 | return; 497 | } 498 | 499 | /* ----------- BUILD & SEND THE ACTUAL MSG ------------ */ 500 | SMTPc_SendBody(sock_id, p_msg, p_err); 501 | if (*p_err != SMTPc_ERR_NONE) { 502 | SMTPc_TRACE_DBG(("Error SMTPc_SendBody. Error: %u\n\r", (unsigned int)*p_err)); 503 | } 504 | } 505 | 506 | 507 | /* 508 | ********************************************************************************************************* 509 | * SMTPc_Disconnect() 510 | * 511 | * Description : (1) Close the connection between client and server. 512 | * 513 | * (a) Send QUIT command 514 | * (b) Close socket 515 | * 516 | * 517 | * Argument(s) : sock_id Socket ID. 518 | * p_err Pointer to variable that will hold the return error code from this 519 | * function : 520 | * 521 | * SMTPc_ERR_NONE No error. 522 | * 523 | * Return(s) : none. 524 | * 525 | * Caller(s) : Application, 526 | * SMTPc_Connect(). 527 | * 528 | * Note(s) : (2) The receiver (client) MUST NOT intentionally close the transmission channel until 529 | * it receives and replies to a QUIT command. 530 | * 531 | * (3) The receiver of the QUIT command MUST send an OK reply, and then close the 532 | * transmission channel. 533 | ********************************************************************************************************* 534 | */ 535 | 536 | void SMTPc_Disconnect (NET_SOCK_ID sock_id, 537 | SMTPc_ERR *p_err) 538 | { 539 | CPU_INT32U completion_code; 540 | NET_ERR err; 541 | 542 | 543 | SMTPc_QUIT(sock_id, &completion_code, p_err); 544 | 545 | NetApp_SockClose(sock_id, 546 | SMTPc_CFG_MAX_CONN_CLOSE_TIMEOUT_MS, 547 | &err); 548 | 549 | *p_err = SMTPc_ERR_NONE; 550 | } 551 | 552 | 553 | /* 554 | ********************************************************************************************************* 555 | * SMTPc_SetMbox() 556 | * 557 | * Description : (1) Populates a SMTPc_MBOX structure with associated name and address. 558 | * 559 | * (a) Perform error checking. 560 | * (b) Copy arguments in structure. 561 | * 562 | * 563 | * Argument(s) : p_mbox SMTPc_MBOX structure to be populated. 564 | * p_name Name of the mailbox owner. 565 | * p_addr Address associated with the mailbox. 566 | * p_err Pointer to variable that will hold the return error code from this 567 | * function : 568 | * 569 | * SMTPc_ERR_NONE No error, structure ready. 570 | * SMTPc_ERR_NULL_ARG Argument 'mbox'/'name' passed a NULL pointer. 571 | * SMTPc_ERR_STR_TOO_LONG Argument addr too long. 572 | * 573 | * Return(s) : none. 574 | * 575 | * Caller(s) : Application. 576 | * 577 | * Note(s) : (2) The name of the mailbox owner is not mandatory. Passing NULL will result in an 578 | * empty string being copied in the structure. 579 | ********************************************************************************************************* 580 | */ 581 | 582 | void SMTPc_SetMbox (SMTPc_MBOX *p_mbox, 583 | CPU_CHAR *p_name, 584 | CPU_CHAR *p_addr, 585 | SMTPc_ERR *p_err) 586 | { 587 | CPU_SIZE_T len; 588 | 589 | 590 | if ((p_mbox == (SMTPc_MBOX *)0) || 591 | (p_addr == (CPU_CHAR *)0)) { 592 | *p_err = SMTPc_ERR_NULL_ARG; 593 | return; 594 | } 595 | 596 | len = Str_Len(p_addr); 597 | if (len >= SMTPc_MBOX_ADDR_LEN) { 598 | *p_err = SMTPc_ERR_STR_TOO_LONG; 599 | return; 600 | } else { 601 | Str_Copy(p_mbox->Addr, p_addr); 602 | } 603 | 604 | if (p_name == (CPU_CHAR *)0) { /* See Note #2. */ 605 | Str_Copy((CPU_CHAR *)p_mbox->NameDisp, 606 | (CPU_CHAR *)""); 607 | } else { 608 | len = Str_Len(p_name); 609 | if (len >= SMTPc_CFG_MBOX_NAME_DISP_LEN) { 610 | *p_err = SMTPc_ERR_STR_TOO_LONG; 611 | return; 612 | } else { 613 | Str_Copy(p_mbox->NameDisp, p_name); 614 | } 615 | } 616 | 617 | *p_err = SMTPc_ERR_NONE; 618 | } 619 | 620 | 621 | /* 622 | ********************************************************************************************************* 623 | * SMTPc_SetMsg() 624 | * 625 | * Description : Sets the various fields of a SMTPc_MSG structure so that it is valid and usable. 626 | * 627 | * Argument(s) : p_msg SMTPc_MSG structure to be initialized. 628 | * p_err Pointer to variable that will hold the return error code from this 629 | * function : 630 | * 631 | * SMTPc_ERR_NONE No error, structure ready. 632 | * SMTPc_ERR_NULL_ARG Argument 'p_msg'/'from' passed a NULL pointer. 633 | * 634 | * Return(s) : none. 635 | * 636 | * Caller(s) : Application. 637 | * 638 | * Note(s) : (1) This function MUST be called after declaring a SMTPc_MSG structure and BEFORE beginning 639 | * to manipulate it. Failure to do so will likely produce run-time errors. 640 | * 641 | * (2) The SMTPc_MSG structure member 'MIMEMsgHdrStruct' is left uninitialized for now, 642 | * MIME extensions not being supported in this version. 643 | ********************************************************************************************************* 644 | */ 645 | 646 | void SMTPc_SetMsg (SMTPc_MSG *p_msg, 647 | SMTPc_ERR *p_err) 648 | { 649 | CPU_INT08U i; 650 | 651 | 652 | if (p_msg == (SMTPc_MSG *)0) { 653 | *p_err = SMTPc_ERR_NULL_ARG; 654 | return; 655 | } 656 | 657 | p_msg->From = (SMTPc_MBOX *)0; 658 | p_msg->Sender = (SMTPc_MBOX *)0; 659 | 660 | /* Set ptr's to NULL or 0 */ 661 | for (i = 0; i < SMTPc_CFG_MSG_MAX_TO; i++) { 662 | p_msg->ToArray[i] = (SMTPc_MBOX *)0; 663 | } 664 | 665 | for (i = 0; i < SMTPc_CFG_MSG_MAX_CC; i++) { 666 | p_msg->CCArray[i] = (SMTPc_MBOX *)0; 667 | } 668 | 669 | for (i = 0; i < SMTPc_CFG_MSG_MAX_BCC; i++) { 670 | p_msg->BCCArray[i] = (SMTPc_MBOX *)0; 671 | } 672 | 673 | for (i = 0; i < SMTPc_CFG_MSG_MAX_ATTACH; i++) { 674 | p_msg->AttachArray[i] = (SMTPc_ATTACH *)0; 675 | } 676 | 677 | p_msg->ReplyTo = (SMTPc_MBOX *)0; 678 | p_msg->ContentBodyMsg = (CPU_CHAR *)0; 679 | p_msg->ContentBodyMsgLen = 0; 680 | p_msg->Subject = DEF_NULL; 681 | /* Clr CPU_CHAR arrays */ 682 | Mem_Clr((void *)p_msg->MsgID, 683 | (CPU_SIZE_T)SMTPc_MIME_ID_LEN); 684 | 685 | SMTPc_TRACE_DBG(("SMTPc_SetMsg() success\n\r")); 686 | 687 | 688 | *p_err = SMTPc_ERR_NONE; 689 | } 690 | 691 | 692 | /* 693 | ********************************************************************************************************* 694 | * SMTPc_SendMail() 695 | * 696 | * Description : Send an email. 697 | * 698 | * Argument(s) : p_host_name Pointer to host name of the SMTP server to contact. Can be also an IP address. 699 | * 700 | * port TCP port to use, or '0' if SMTPc_DFLT_PORT. 701 | * 702 | * p_username Pointer to user name, if authentication enabled. 703 | * 704 | * p_pwd Pointer to password, if authentication enabled. 705 | * 706 | * p_secure_cfg Pointer to the secure configuration (TLS/SSL): 707 | * 708 | * DEF_NULL, if no security enabled. 709 | * Pointer to a structure that contains the parameters. 710 | * 711 | * p_msg SMTPc_MSG structure encapsulating the message to send. 712 | * 713 | * p_err Pointer to variable that will hold the return error from this 714 | * function: 715 | * 716 | * SMTPc_ERR_NONE No error, TCP connection established. 717 | * SMTPc_ERR_INVALID_ADDR Argument server_addr_ascii and/or client_addr_ascii invalid 718 | * 719 | * ------ RETURNED BY SMTPc_Connect : ------ 720 | * SMTPc_ERR_NULL_ARG Argument 'username'/'pw' passed a NULL pointer. 721 | * SMTPc_ERR_SOCK_OPEN_FAILED Error opening socket. 722 | * SMTPc_ERR_SOCK_CONN_FAILED Error connecting to server. 723 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 724 | * SMTPc_ERR_REP Error with reply. 725 | * SMTPc_ERR_SECURE_NOT_AVAIL No secure mode available. 726 | * SMTPc_ERR_ENCODE Error encoding credentials. 727 | * SMTPc_ERR_AUTH_FAILED Error authenticating user. 728 | * 729 | * ------- RETURNED BY SMTPc_SendMsg : ------ 730 | * SMTPc_ERR_NULL_ARG Argument 'p_msg' passed a NULL pointer. 731 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 732 | * SMTPc_ERR_REP Error with reply. 733 | * SMTPc_ERR_TX_FAILED Error querying server. 734 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 735 | * SMTPc_ERR_REP Error with reply. 736 | * SMTPc_ERR_TX_FAILED Error querying server. 737 | * SMTPc_ERR_LINE_TOO_LONG Line limit exceeded. 738 | * Return(s) : none. 739 | * 740 | * Caller(s) : Application. 741 | * 742 | * Note(s) : none. 743 | ********************************************************************************************************* 744 | */ 745 | 746 | void SMTPc_SendMail (CPU_CHAR *p_host_name, 747 | CPU_INT16U port, 748 | CPU_CHAR *p_username, 749 | CPU_CHAR *p_pwd, 750 | NET_APP_SOCK_SECURE_CFG *p_secure_cfg, 751 | SMTPc_MSG *p_msg, 752 | SMTPc_ERR *p_err) 753 | { 754 | NET_SOCK_ID sock; 755 | 756 | /* -------------- CONNECT TO SMTP SEVER --------------- */ 757 | sock = SMTPc_Connect(p_host_name, 758 | port, 759 | p_username, 760 | p_pwd, 761 | p_secure_cfg, 762 | p_err); 763 | if (*p_err != SMTPc_ERR_NONE) { 764 | return; 765 | } 766 | /* ----------------- SEND THE MESSAGE ----------------- */ 767 | SMTPc_SendMsg(sock, p_msg, p_err); 768 | if (*p_err != SMTPc_ERR_NONE) { 769 | return; 770 | } 771 | /* ----------- DISCONNECT FROM SMTP SERVER ------------ */ 772 | SMTPc_Disconnect(sock, p_err); 773 | } 774 | 775 | 776 | /* 777 | ********************************************************************************************************* 778 | * LOCAL FUNCTIONS 779 | ********************************************************************************************************* 780 | */ 781 | 782 | /* 783 | ********************************************************************************************************* 784 | * SMTPc_RxReply() 785 | * 786 | * Description : Receive and process reply from the SMTP server. 787 | * 788 | * Argument(s) : sock_id Socket ID. 789 | * perr Pointer to variable that will hold the return error code from this 790 | * function : 791 | * 792 | * SMTPc_ERR_NONE No error. 793 | * SMTPc_ERR_RX_FAILED Error receiving the reply. 794 | * 795 | * Return(s) : Complete reply from the server, if NO reception error. 796 | * 797 | * (CPU_CHAR *)0, otherwise. 798 | * 799 | * Caller(s) : SMTPc_Connect(), 800 | * SMTPc_SendMsg(), 801 | * SMTPc_HELO(), 802 | * SMTPc_MAIL(), 803 | * SMTPc_RCPT(), 804 | * SMTPc_DATA(), 805 | * SMTPc_RSET(), 806 | * SMTPc_QUIT(). 807 | * 808 | * Note(s) : (1) Server reply is at least 3 characters long (3 digits), plus CRLF. Hence, receiving 809 | * less than that automatically indicates an error. 810 | ********************************************************************************************************* 811 | */ 812 | 813 | static CPU_CHAR *SMTPc_RxReply (NET_SOCK_ID sock_id, 814 | SMTPc_ERR *perr) 815 | { 816 | NET_SOCK_RTN_CODE rx_len; 817 | NET_ERR err; 818 | 819 | 820 | /* ---------------------- RX REPLY -------------------- */ 821 | rx_len = NetSock_RxData(sock_id, 822 | SMTPc_Comm_Buf, 823 | SMTPc_COMM_BUF_LEN - 1, 824 | NET_SOCK_FLAG_NONE, 825 | &err); 826 | 827 | /* See Note #1. */ 828 | if ((rx_len == NET_SOCK_BSD_ERR_RX) || 829 | (rx_len <= 4 )) { 830 | *perr = SMTPc_ERR_RX_FAILED; 831 | return ((CPU_CHAR *)0); 832 | } 833 | 834 | SMTPc_Comm_Buf[rx_len] = '\0'; 835 | 836 | *perr = SMTPc_ERR_NONE; 837 | 838 | return (SMTPc_Comm_Buf); 839 | } 840 | 841 | 842 | /* 843 | ********************************************************************************************************* 844 | * SMTPc_ParseReply() 845 | * 846 | * Description : (1) Process reply received from the SMTP server. 847 | * 848 | * (a) Parse reply 849 | * (b) Interpret reply 850 | * 851 | * 852 | * Argument(s) : server_reply Complete reply received from the server. 853 | * completion_code Numeric value returned by server indicating command status. 854 | * perr Pointer to variable that will hold the return error code from this 855 | * function : 856 | * 857 | * SMTPc_ERR_REP_TOO_SHORT Reply not long enough. 858 | * SMTPc_ERR_REP_POS No error, positive reply received. 859 | * SMTPc_ERR_REP_INTER No error, intermediate reply received. 860 | * SMTPc_ERR_REP_NEG Negative reply received. 861 | * 862 | * Return(s) : none. 863 | * 864 | * Caller(s) : SMTPc_Connect(), 865 | * SMTPc_SendMsg(), 866 | * SMTPc_HELO(), 867 | * SMTPc_MAIL(), 868 | * SMTPc_RCPT(), 869 | * SMTPc_DATA(), 870 | * SMTPc_RSET(), 871 | * SMTPc_QUIT(). 872 | * 873 | * Note(s) : none. 874 | ********************************************************************************************************* 875 | */ 876 | 877 | static void SMTPc_ParseReply (CPU_CHAR *server_reply, 878 | CPU_INT32U *completion_code, 879 | SMTPc_ERR *perr) 880 | { 881 | CPU_INT08U code_first_dig; 882 | CPU_INT08U len; 883 | 884 | /* -------------------- PARSE REPLY ------------------ */ 885 | len = Str_Len(server_reply); /* Make sure string is at least 3 + 1 char long. */ 886 | if (len < 4) { 887 | *perr = SMTPc_ERR_REP_TOO_SHORT; 888 | return; 889 | } 890 | 891 | *completion_code = Str_ParseNbr_Int32U(server_reply, DEF_NULL, 10); 892 | SMTPc_TRACE_DBG(("Code: %u\n\r", (unsigned int)*completion_code)); 893 | 894 | 895 | /* ------------------ INTERPRET REPLY ----------------- */ 896 | code_first_dig = *completion_code / 100; 897 | switch (code_first_dig) { 898 | case SMTPc_REP_POS_COMPLET_GRP: /* Positive reply. */ 899 | *perr = SMTPc_ERR_REP_POS; 900 | break; 901 | 902 | case SMTPc_REP_POS_PRELIM_GRP: /* Intermediate reply. */ 903 | case SMTPc_REP_POS_INTER_GRP: 904 | *perr = SMTPc_ERR_REP_INTER; 905 | break; 906 | 907 | case SMTPc_REP_NEG_TRANS_COMPLET_GRP: /* Negative reply. */ 908 | case SMTPc_REP_NEG_COMPLET_GRP: 909 | *perr = SMTPc_ERR_REP_NEG; 910 | break; 911 | 912 | default: /* Should never happen, interpreted as negative. */ 913 | *perr = SMTPc_ERR_REP_NEG; 914 | break; 915 | } 916 | } 917 | 918 | 919 | /* 920 | ********************************************************************************************************* 921 | * SMTPc_QueryServer() 922 | * 923 | * Description : Send a query (or anything else) to the server. 924 | * 925 | * Argument(s) : sock_id Socket ID. 926 | * query Query in question. 927 | * len Length of message to transmit 928 | * perr Pointer to variable that will hold the return error code from this 929 | * function : 930 | * 931 | * SMTPc_ERR_NONE No error. 932 | * 933 | * ----- RETURNED BY NetSock_TxData() : ----- 934 | * See uC/TCPIP source code. 935 | * 936 | * Return(s) : none. 937 | * 938 | * Caller(s) : SMTPc_SendBody(), 939 | * SMTPc_BuildHdr(), 940 | * SMTPc_HELO(), 941 | * SMTPc_MAIL(), 942 | * SMTPc_RCPT(), 943 | * SMTPc_DATA(), 944 | * SMTPc_RSET(), 945 | * SMTPc_QUIT(). 946 | * 947 | * Note(s) : none. 948 | ********************************************************************************************************* 949 | */ 950 | 951 | static void SMTPc_QueryServer (NET_SOCK_ID sock_id, 952 | CPU_CHAR *query, 953 | CPU_INT32U len, 954 | SMTPc_ERR *perr) 955 | { 956 | NET_SOCK_RTN_CODE rtn_code; 957 | CPU_INT32U cur_pos; 958 | NET_ERR err; 959 | 960 | /* ---------------------- TX QUERY -------------------- */ 961 | cur_pos = 0; 962 | 963 | do { 964 | rtn_code = NetSock_TxData( sock_id, 965 | &query[cur_pos], 966 | len, 967 | 0, 968 | &err); 969 | 970 | cur_pos = cur_pos + rtn_code; 971 | len = len - rtn_code; 972 | 973 | } while ((len != 0) && (rtn_code != NET_SOCK_BSD_ERR_TX)); 974 | 975 | if (rtn_code != NET_SOCK_BSD_ERR_TX) { 976 | *perr = SMTPc_ERR_NONE; 977 | } 978 | } 979 | 980 | 981 | /* 982 | ********************************************************************************************************* 983 | * SMTPc_SendBody() 984 | * 985 | * Description : (1) Prepare and send the actual data of the message, i.e. the body part of the message 986 | * content. 987 | * 988 | * (a) Built headers and transmit 989 | * (b) Transmit body content 990 | * (c) Prepare and transmit attachment(s) 991 | * (d) Transmit "end of mail data" indicator 992 | * (e) Receive the confirmation reply 993 | * 994 | * 995 | * Argument(s) : sock_id Socket ID. 996 | * msg SMTPc_MSG structure encapsulating the message to send. 997 | * perr Pointer to variable that will hold the return error code from this 998 | * function : 999 | * 1000 | * SMTPc_ERR_NONE No error. 1001 | * SMTPc_ERR_TX_FAILED Error querying server. 1002 | * 1003 | * ----- RETURNED BY SMTPc_BuildHdr() : ----- 1004 | * SMTPc_ERR_NONE No error. 1005 | * SMTPc_ERR_LINE_TOO_LONG Line limit exceeded. 1006 | * SMTPc_ERR_TX_FAILED Error querying server. 1007 | * 1008 | * Return(s) : none. 1009 | * 1010 | * Caller(s) : SMTPc_SendMsg(). 1011 | * 1012 | * Note(s) : (2) The current implementation does not insert the names of the mailbox owners (member 1013 | * NameDisp of structure SMTPc_MBOX). 1014 | ********************************************************************************************************* 1015 | */ 1016 | 1017 | static void SMTPc_SendBody (NET_SOCK_ID sock_id, 1018 | SMTPc_MSG *msg, 1019 | SMTPc_ERR *perr) 1020 | { 1021 | CPU_SIZE_T len; 1022 | CPU_INT32U cur_wr_ix; 1023 | CPU_INT08U i; 1024 | CPU_INT32U line_len; 1025 | CPU_CHAR *hdr; 1026 | CPU_CHAR *reply; 1027 | CPU_INT32U completion_code; 1028 | 1029 | 1030 | cur_wr_ix = 0; 1031 | line_len = 0; 1032 | 1033 | /* ------------------- BUILT HEADERS ------------------ */ 1034 | /* Header "From: ". */ 1035 | hdr = (CPU_CHAR *)SMTPc_HDR_FROM; 1036 | cur_wr_ix = SMTPc_BuildHdr( sock_id, /* Addr */ 1037 | SMTPc_Comm_Buf, 1038 | SMTPc_COMM_BUF_LEN, 1039 | cur_wr_ix, 1040 | hdr, 1041 | msg->From->Addr, 1042 | &line_len, 1043 | perr); 1044 | if (*perr != SMTPc_ERR_NONE) { 1045 | return; 1046 | } 1047 | 1048 | 1049 | if (msg->Sender != (SMTPc_MBOX *)0) { /* Header "Sender: ". */ 1050 | hdr = (CPU_CHAR *)SMTPc_HDR_SENDER; 1051 | cur_wr_ix = SMTPc_BuildHdr( sock_id, /* Addr */ 1052 | SMTPc_Comm_Buf, 1053 | SMTPc_COMM_BUF_LEN, 1054 | cur_wr_ix, 1055 | hdr, 1056 | msg->Sender->Addr, 1057 | &line_len, 1058 | perr); 1059 | if (*perr != SMTPc_ERR_NONE) { 1060 | return; 1061 | } 1062 | } 1063 | 1064 | 1065 | 1066 | /* Header "To: ". */ 1067 | hdr = (CPU_CHAR *)SMTPc_HDR_TO; 1068 | for (i = 0; (i < SMTPc_CFG_MSG_MAX_TO) && (msg->ToArray[i] != (SMTPc_MBOX *)0); i++) { 1069 | cur_wr_ix = SMTPc_BuildHdr( sock_id, 1070 | SMTPc_Comm_Buf, 1071 | SMTPc_COMM_BUF_LEN, 1072 | cur_wr_ix, 1073 | hdr, 1074 | msg->ToArray[i]->Addr, 1075 | &line_len, 1076 | perr); 1077 | if (*perr != SMTPc_ERR_NONE) { 1078 | return; 1079 | } 1080 | hdr = (CPU_CHAR *)0; 1081 | } 1082 | 1083 | 1084 | /* Header "Reply-to: ". */ 1085 | hdr = (CPU_CHAR *)SMTPc_HDR_REPLYTO; 1086 | if (msg->ReplyTo != (SMTPc_MBOX *)0) { 1087 | cur_wr_ix = SMTPc_BuildHdr( sock_id, 1088 | SMTPc_Comm_Buf, 1089 | SMTPc_COMM_BUF_LEN, 1090 | cur_wr_ix, 1091 | hdr, 1092 | msg->ReplyTo->Addr, 1093 | &line_len, 1094 | perr); 1095 | if (*perr != SMTPc_ERR_NONE) { 1096 | return; 1097 | } 1098 | hdr = (CPU_CHAR *)0; 1099 | } 1100 | 1101 | 1102 | /* Header "CC: ". */ 1103 | hdr = (CPU_CHAR *)SMTPc_HDR_CC; 1104 | for (i = 0; (i < SMTPc_CFG_MSG_MAX_CC) && (msg->CCArray[i] != (SMTPc_MBOX *)0); i++) { 1105 | cur_wr_ix = SMTPc_BuildHdr( sock_id, 1106 | SMTPc_Comm_Buf, 1107 | SMTPc_COMM_BUF_LEN, 1108 | cur_wr_ix, 1109 | hdr, 1110 | msg->CCArray[i]->Addr, 1111 | &line_len, 1112 | perr); 1113 | if (*perr != SMTPc_ERR_NONE) { 1114 | return; 1115 | } 1116 | hdr = (CPU_CHAR *)0; 1117 | } 1118 | 1119 | 1120 | if (msg->Subject != (CPU_CHAR *)0) { /* Header "Subject: ". */ 1121 | cur_wr_ix = SMTPc_BuildHdr((NET_SOCK_ID ) sock_id, 1122 | (CPU_CHAR *) SMTPc_Comm_Buf, 1123 | (CPU_INT32U ) SMTPc_COMM_BUF_LEN, 1124 | (CPU_INT32U ) cur_wr_ix, 1125 | (CPU_CHAR *) SMTPc_HDR_SUBJECT, 1126 | (CPU_CHAR *) msg->Subject, 1127 | (CPU_INT32U *)&line_len, 1128 | (SMTPc_ERR *) perr); 1129 | if (*perr != SMTPc_ERR_NONE) { 1130 | return; 1131 | } 1132 | } 1133 | /* ----------- INSERT HEADER/BODY DELIMITER ----------- */ 1134 | Mem_Copy(&SMTPc_Comm_Buf[cur_wr_ix], SMTPc_CRLF, SMTPc_CRLF_SIZE); 1135 | cur_wr_ix += SMTPc_CRLF_SIZE; 1136 | 1137 | /* ---------------- TX CONTENT HEADERS ---------------- */ 1138 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, cur_wr_ix, perr); 1139 | if (*perr != SMTPc_ERR_NONE) { 1140 | *perr = SMTPc_ERR_TX_FAILED; 1141 | return; 1142 | } 1143 | 1144 | 1145 | /* ------------------ TX BODY CONTENT ----------------- */ 1146 | SMTPc_QueryServer(sock_id, msg->ContentBodyMsg, msg->ContentBodyMsgLen, perr); 1147 | if (*perr != SMTPc_ERR_NONE) { 1148 | *perr = SMTPc_ERR_TX_FAILED; 1149 | return; 1150 | } 1151 | 1152 | 1153 | 1154 | /* ------------ PREPARE & TX ATTACHMENT(S) ------------ */ 1155 | /* #### Not currently implemented. */ 1156 | 1157 | 1158 | 1159 | /* ----------- TX END OF MAIL DATA INDICATOR ---------- */ 1160 | Mem_Copy(SMTPc_Comm_Buf, SMTPc_EOM, sizeof(SMTPc_EOM)); 1161 | len = Str_Len(SMTPc_Comm_Buf); 1162 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, len, perr); 1163 | if (*perr != SMTPc_ERR_NONE) { 1164 | *perr = SMTPc_ERR_TX_FAILED; 1165 | return; 1166 | } 1167 | 1168 | /* --------------- RX CONFIRMATION REPLY -------------- */ 1169 | reply = SMTPc_RxReply(sock_id, perr); 1170 | if (*perr != SMTPc_ERR_NONE) { 1171 | *perr = SMTPc_ERR_RX_FAILED; 1172 | return; 1173 | } 1174 | 1175 | SMTPc_ParseReply(reply, &completion_code, perr); 1176 | switch (*perr) { 1177 | case SMTPc_ERR_REP_POS: 1178 | if (completion_code == SMTPc_REP_250) { 1179 | *perr = SMTPc_ERR_NONE; 1180 | } 1181 | break; 1182 | 1183 | default: 1184 | *perr = SMTPc_ERR_REP; 1185 | break; 1186 | } 1187 | 1188 | if (*perr != SMTPc_ERR_NONE) { 1189 | if ((completion_code != SMTPc_REP_421) && 1190 | (completion_code != SMTPc_REP_221)) { 1191 | SMTPc_RSET(sock_id, &completion_code, perr); 1192 | } 1193 | *perr = SMTPc_ERR_REP; 1194 | } 1195 | } 1196 | 1197 | 1198 | /* 1199 | ********************************************************************************************************* 1200 | * SMTPc_BuildHdr() 1201 | * 1202 | * Description : (1) Prepare (and send if necessary) the message content's headers. 1203 | * 1204 | * (a) Calculate needed space 1205 | * (b) Send data, if necessary 1206 | * (c) Build header 1207 | * 1208 | * 1209 | * Argument(s) : sock_id Socket ID. 1210 | * buf Buffer used to store the headers prior to their expedition. 1211 | * buf_size Size of buffer. 1212 | * buf_wr_ix Index of current "write" position. 1213 | * hdr Header name. 1214 | * val Value associated with header. 1215 | * line_len Current line total length. 1216 | * perr Pointer to variable that will hold the return error code from this 1217 | * function : 1218 | * 1219 | * SMTPc_ERR_NONE No error. 1220 | * SMTPc_ERR_LINE_TOO_LONG Line limit exceeded. 1221 | * SMTPc_ERR_TX_FAILED Error querying server. 1222 | * 1223 | * Return(s) : "Write" position in buffer. 1224 | * 1225 | * Caller(s) : SMTPc_SendBody(). 1226 | * 1227 | * Note(s) : (2) If the parameter "hdr" is (CPU_CHAR *)0, et means that it's already been passed in a 1228 | * previous call. Hence, a "," will be inserted in the buffer prior to the value. 1229 | * 1230 | * (3) If the SMTP line limit is exceeded, perr is set to SMTPc_ERR_LINE_TOO_LONG and the 1231 | * function returns without having added the header. 1232 | * 1233 | * (4) This implementation transmit the headers buffer if the next header is too large to 1234 | * be inserted in the remaining buffer space. 1235 | * 1236 | * Note that NO EXACT calculations are performed here; a conservative approach is 1237 | * brought forward, without actually optimizing the process (i.e. a buffer could be 1238 | * sent even though a few more characters could have been inserted). 1239 | * 1240 | * (5) CRLF is inserted even though more entries are still to come for a particular header 1241 | * (line folding is performed even if unnecessary). 1242 | ********************************************************************************************************* 1243 | */ 1244 | 1245 | static CPU_INT32U SMTPc_BuildHdr (NET_SOCK_ID sock_id, 1246 | CPU_CHAR *buf, 1247 | CPU_INT32U buf_size, 1248 | CPU_INT32U buf_wr_ix, 1249 | CPU_CHAR *hdr, 1250 | CPU_CHAR *val, 1251 | CPU_INT32U *line_len, 1252 | SMTPc_ERR *perr) 1253 | { 1254 | CPU_INT32U hdr_len; 1255 | CPU_INT32U val_len; 1256 | CPU_INT32U total_len; 1257 | 1258 | /* ------------- CALCULATE NECESSARY SPACE ------------ */ 1259 | if (hdr == (CPU_CHAR *)0) { 1260 | hdr_len = 0; 1261 | } else { 1262 | hdr_len = Str_Len(hdr); 1263 | } 1264 | 1265 | if (val == (CPU_CHAR *)0) { 1266 | val_len = 0; 1267 | } else { 1268 | val_len = Str_Len(val); 1269 | } 1270 | 1271 | total_len = hdr_len + val_len + 2; 1272 | 1273 | if ((*line_len + total_len) > SMTPc_LINE_LEN_LIM) { /* See Note #3. */ 1274 | *perr = SMTPc_ERR_LINE_TOO_LONG; 1275 | return (buf_wr_ix); 1276 | } 1277 | 1278 | 1279 | 1280 | /* -------------- SEND DATA, IF NECESSARY ------------- */ 1281 | /* See Note #4. */ 1282 | if ((buf_size - buf_wr_ix) < total_len) { 1283 | SMTPc_QueryServer(sock_id, buf, buf_wr_ix, perr); 1284 | if (*perr != SMTPc_ERR_NONE) { 1285 | *perr = SMTPc_ERR_TX_FAILED; 1286 | return buf_wr_ix; 1287 | } 1288 | buf_wr_ix = 0; 1289 | } 1290 | 1291 | 1292 | /* ------------------ BUILDING HEADER ----------------- */ 1293 | if (hdr != (CPU_CHAR *)0) { 1294 | Mem_Copy(buf + buf_wr_ix, hdr, hdr_len); 1295 | buf_wr_ix += hdr_len; 1296 | *line_len += hdr_len; 1297 | } else { /* Not first item, adding ','. */ 1298 | Mem_Copy(buf + buf_wr_ix, " ,", 2); 1299 | buf_wr_ix += 2; 1300 | *line_len += 2; 1301 | } 1302 | if (val != (CPU_CHAR *)0) { 1303 | Mem_Copy(buf + buf_wr_ix, val, val_len); 1304 | buf_wr_ix += val_len; 1305 | *line_len += val_len; 1306 | } 1307 | 1308 | Mem_Copy(buf + buf_wr_ix, SMTPc_CRLF, 2); /* See Note #5. */ 1309 | buf_wr_ix += 2; 1310 | *line_len = 0; 1311 | 1312 | 1313 | buf[buf_wr_ix] = '\0'; 1314 | SMTPc_TRACE_DBG(("String: %s\n", buf)); 1315 | 1316 | *perr = SMTPc_ERR_NONE; 1317 | return (buf_wr_ix); 1318 | } 1319 | 1320 | 1321 | /* 1322 | ********************************************************************************************************* 1323 | * SMTPc_HELO() 1324 | * 1325 | * Description : (1) Build the HELO command, send it to the server and validate reply. 1326 | * 1327 | * (a) Send command to the server 1328 | * (b) Receive server's reply and validate 1329 | * 1330 | * 1331 | * Argument(s) : sock_id Socket ID. 1332 | * 1333 | * completion_code Numeric value returned by server indicating command status. 1334 | * 1335 | * perr Pointer to variable that will hold the return error code from this 1336 | * function : 1337 | * 1338 | * SMTPc_ERR_NONE No error. 1339 | * SMTPc_ERR_TX_FAILED Error querying server. 1340 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 1341 | * SMTPc_ERR_REP Error with reply. 1342 | * 1343 | * Return(s) : Complete reply from the server, if NO reception error. 1344 | * 1345 | * (CPU_CHAR *)0, otherwise. 1346 | * 1347 | * Caller(s) : SMTPc_Connect(). 1348 | * 1349 | * Note(s) : (2) From RFC #2821, "the HELO command is used to identify the SMTP client to the SMTP 1350 | * server". 1351 | * 1352 | * (3) The server will send a 250 "Requested mail action okay, completed" reply upon 1353 | * success. A positive reply is the only reply that will lead to a "SMTPc_ERR_NONE" 1354 | * error return code. 1355 | * 1356 | * (4) This implementation will accept reply 250, as well as any other positive reply. 1357 | * 1358 | * (5) From RFC #2821, section 4.1.3 Address Literals: 1359 | * 1360 | * For IPv4 addresses, this form uses four small decimal integers separated 1361 | * by dots and enclosed by brackets such as [123.255.37.2], which 1362 | * indicates an (IPv4) Internet Address in sequence-of-octets form. For 1363 | * IPv6 and other forms of addressing that might eventually be 1364 | * standardized, the form consists of a standardized "tag" that 1365 | * identifies the address syntax, a colon, and the address itself, in a 1366 | * format specified as part of the IPv6 standards. 1367 | * 1368 | * 1369 | ********************************************************************************************************* 1370 | */ 1371 | 1372 | static CPU_CHAR *SMTPc_HELO (NET_SOCK_ID sock_id, 1373 | CPU_INT32U *completion_code, 1374 | SMTPc_ERR *perr) 1375 | { 1376 | CPU_CHAR *reply; 1377 | CPU_SIZE_T len; 1378 | CPU_INT08U client_addr[NET_CONN_ADDR_LEN_MAX]; 1379 | NET_SOCK_FAMILY client_addr_family; 1380 | NET_ERR err_net; 1381 | CPU_CHAR client_addr_ascii[NET_ASCII_LEN_MAX_ADDR_IP]; 1382 | NET_IPv4_ADDR ipv4_client_addr; 1383 | 1384 | /* Get the IP address used in the conn. */ 1385 | NetSock_GetLocalIPAddr(sock_id, 1386 | client_addr, 1387 | &client_addr_family, 1388 | &err_net); 1389 | if (err_net != NET_SOCK_ERR_NONE) { 1390 | *perr = SMTPc_ERR_TX_FAILED; 1391 | return ((CPU_CHAR *)0); 1392 | } 1393 | /* Format the message depending of the address family. */ 1394 | 1395 | switch (client_addr_family) { 1396 | #ifdef NET_IPv4_MODULE_EN 1397 | case NET_SOCK_FAMILY_IP_V4: 1398 | 1399 | ipv4_client_addr = NET_UTIL_NET_TO_HOST_32(*(CPU_INT32U *)client_addr); 1400 | NetASCII_IPv4_to_Str(ipv4_client_addr, client_addr_ascii, DEF_NO, &err_net); 1401 | 1402 | if (err_net != NET_ASCII_ERR_NONE) { 1403 | *perr = SMTPc_ERR_TX_FAILED; 1404 | return ((CPU_CHAR *)0); 1405 | } 1406 | 1407 | Str_Copy(SMTPc_Comm_Buf, SMTPc_CMD_HELO); 1408 | Str_Cat(SMTPc_Comm_Buf," ["); 1409 | Str_Cat(SMTPc_Comm_Buf,client_addr_ascii); 1410 | Str_Cat(SMTPc_Comm_Buf,"]\r\n"); 1411 | break; 1412 | #endif 1413 | 1414 | #ifdef NET_IPv6_MODULE_EN 1415 | case NET_SOCK_FAMILY_IP_V6: 1416 | 1417 | NetASCII_IPv6_to_Str((NET_IPv6_ADDR *) client_addr, 1418 | client_addr_ascii, 1419 | DEF_NO, 1420 | DEF_NO, 1421 | &err_net); 1422 | if (err_net != NET_ASCII_ERR_NONE) { 1423 | *perr = SMTPc_ERR_TX_FAILED; 1424 | return ((CPU_CHAR *)0); 1425 | } 1426 | 1427 | Str_Copy(SMTPc_Comm_Buf, SMTPc_CMD_HELO); 1428 | Str_Cat(SMTPc_Comm_Buf, " ["); 1429 | Str_Cat(SMTPc_Comm_Buf, SMTPc_TAG_IPv6); 1430 | Str_Cat(SMTPc_Comm_Buf, " "); 1431 | Str_Cat(SMTPc_Comm_Buf, client_addr_ascii); 1432 | Str_Cat(SMTPc_Comm_Buf, "]\r\n"); 1433 | break; 1434 | #endif 1435 | default: 1436 | *perr = SMTPc_ERR_TX_FAILED; 1437 | return ((CPU_CHAR *)0); 1438 | } 1439 | 1440 | len = Str_Len(SMTPc_Comm_Buf); 1441 | /* Send HELO Query. */ 1442 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, len, perr); 1443 | if (*perr != SMTPc_ERR_NONE) { 1444 | *perr = SMTPc_ERR_TX_FAILED; 1445 | return ((CPU_CHAR *)0); 1446 | } 1447 | 1448 | /* --------- RX SERVER'S REPLY & VALIDATE ------------- */ 1449 | reply = SMTPc_RxReply(sock_id, perr); /* See Note #3. */ 1450 | if (*perr != SMTPc_ERR_NONE) { 1451 | *perr = SMTPc_ERR_RX_FAILED; 1452 | return ((CPU_CHAR *)0); 1453 | } 1454 | 1455 | SMTPc_ParseReply(reply, completion_code, perr); /* See Note #4. */ 1456 | switch (*perr) { 1457 | case SMTPc_ERR_REP_POS: /* If any pos rep... */ 1458 | *perr = SMTPc_ERR_NONE; /* ... no err. */ 1459 | break; 1460 | 1461 | case SMTPc_ERR_REP_TOO_SHORT: 1462 | *perr = SMTPc_ERR_REP; 1463 | reply = (CPU_CHAR *)0; 1464 | break; 1465 | 1466 | default: 1467 | *perr = SMTPc_ERR_REP; 1468 | break; 1469 | } 1470 | 1471 | return (reply); 1472 | } 1473 | 1474 | 1475 | /* 1476 | ********************************************************************************************************* 1477 | * SMTPc_AUTH() 1478 | * 1479 | * Description : (1) Build the AUTH command, send it to the server and validate reply. 1480 | * 1481 | * (a) Encode username & password 1482 | * (b) Send command to the server 1483 | * (c) Receive server's reply and validate 1484 | * 1485 | * 1486 | * Argument(s) : sock_id Socket ID. 1487 | * username Mailbox username name for authentication. 1488 | * pw Mailbox password for authentication. 1489 | * completion_code Numeric value returned by server indicating command status. 1490 | * perr Pointer to variable that will hold the return error code from this 1491 | * function : 1492 | * 1493 | * SMTPc_ERR_NONE No error. 1494 | * SMTPc_ERR_TX_FAILED Error querying server. 1495 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 1496 | * SMTPc_ERR_REP Error with reply. 1497 | * SMTPc_ERR_ENCODE Error encoding credentials. 1498 | * SMTPc_ERR_AUTH_FAILED Error authenticating user. 1499 | * 1500 | * Return(s) : Complete reply from the server, if NO reception error. 1501 | * 1502 | * (CPU_CHAR *)0, otherwise. 1503 | * 1504 | * Caller(s) : SMTPc_Connect(). 1505 | * 1506 | * Note(s) : (2) The user's credentials are transmitted to the server using a base 64 encoding and 1507 | * formated according to RFC #4616. From Section 2 'PLAIN SALS Mechanism' "The client 1508 | * presents the authorization identity (identity to act as), followed by a NUL (U+0000) 1509 | * character, followed by the authentication identity (identity whose password will be 1510 | * used), followed by a NUL (U+0000) character, followed by the clear-text password. 1511 | * As with other SASL mechanisms, the client does not provide an authorization identity 1512 | * when it wishes the server to derive an identity from the credentials and use that 1513 | * as the authorization identity." 1514 | * 1515 | * (3) The server will send a 235 "Authentication successful" reply upon success. A positive 1516 | * reply is the only reply that will lead to a "SMTPc_ERR_NONE" error return code. 1517 | * 1518 | * (4) This implementation will accept reply 235, as well as any other positive reply. 1519 | ********************************************************************************************************* 1520 | */ 1521 | 1522 | #if (SMTPc_CFG_AUTH_EN == DEF_ENABLED) 1523 | static CPU_CHAR *SMTPc_AUTH (NET_SOCK_ID sock_id, 1524 | CPU_CHAR *username, 1525 | CPU_CHAR *pw, 1526 | CPU_INT32U *completion_code, 1527 | SMTPc_ERR *perr) 1528 | { 1529 | CPU_CHAR unencoded_buf[SMTPc_ENCODER_BASE54_IN_MAX_LEN]; 1530 | CPU_CHAR encoded_buf[SMTPc_ENCODER_BASE64_OUT_MAX_LEN]; 1531 | CPU_INT16U unencoded_len; 1532 | CPU_CHAR *reply; 1533 | CPU_INT16U wr_ix; 1534 | CPU_SIZE_T len; 1535 | NET_ERR net_err; 1536 | 1537 | /* -------------- ENCODE USERNAME & PW ---------------- */ 1538 | /* See Note #2. */ 1539 | wr_ix = 0; 1540 | unencoded_buf[wr_ix] = SMTPc_ENCODER_BASE64_DELIMITER_CHAR; 1541 | wr_ix++; 1542 | 1543 | Str_Copy(&unencoded_buf[wr_ix], username); 1544 | wr_ix += Str_Len(username); 1545 | 1546 | unencoded_buf[wr_ix] = SMTPc_ENCODER_BASE64_DELIMITER_CHAR; 1547 | wr_ix++; 1548 | 1549 | Str_Copy(&unencoded_buf[wr_ix], pw); 1550 | unencoded_len = wr_ix + Str_Len(pw); 1551 | 1552 | /* Base 64 encoding. */ 1553 | NetBase64_Encode (unencoded_buf, unencoded_len, encoded_buf, SMTPc_ENCODER_BASE64_OUT_MAX_LEN, &net_err); 1554 | if (net_err != NET_ERR_NONE) { 1555 | *perr = SMTPc_ERR_ENCODE; 1556 | return ((CPU_CHAR *)0); 1557 | } 1558 | 1559 | /* ------------------ TX CMD TO SERVER ---------------- */ 1560 | Str_Copy(SMTPc_Comm_Buf, SMTPc_CMD_AUTH); 1561 | Str_Cat(SMTPc_Comm_Buf, " "); 1562 | Str_Cat(SMTPc_Comm_Buf, SMTPc_CMD_AUTH_MECHANISM_PLAIN); 1563 | Str_Cat(SMTPc_Comm_Buf, " "); 1564 | Str_Cat(SMTPc_Comm_Buf, encoded_buf); 1565 | Str_Cat(SMTPc_Comm_Buf, "\r\n"); 1566 | len = Str_Len(SMTPc_Comm_Buf); 1567 | 1568 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, len, perr); 1569 | if (*perr != SMTPc_ERR_NONE) { 1570 | *perr = SMTPc_ERR_TX_FAILED; 1571 | return ((CPU_CHAR *)0); 1572 | } 1573 | 1574 | /* ---------- RX SERVER'S RESPONSE & VALIDATE --------- */ 1575 | reply = SMTPc_RxReply(sock_id, perr); /* See Note #3. */ 1576 | if (*perr != SMTPc_ERR_NONE) { 1577 | *perr = SMTPc_ERR_RX_FAILED; 1578 | return ((CPU_CHAR *)0); 1579 | } 1580 | 1581 | 1582 | SMTPc_ParseReply(reply, completion_code, perr); /* See Note #4. */ 1583 | switch (*perr) { 1584 | case SMTPc_ERR_REP_POS: /* If any pos rep... */ 1585 | *perr = SMTPc_ERR_NONE; /* ... no err. */ 1586 | break; 1587 | 1588 | case SMTPc_ERR_REP_NEG: 1589 | if (*completion_code == SMTPc_REP_535) { 1590 | *perr = SMTPc_ERR_AUTH_FAILED; 1591 | } else { 1592 | *perr = SMTPc_ERR_REP; 1593 | } 1594 | break; 1595 | 1596 | case SMTPc_ERR_REP_TOO_SHORT: 1597 | *perr = SMTPc_ERR_REP; 1598 | reply = (CPU_CHAR *)0; 1599 | break; 1600 | 1601 | default: 1602 | *perr = SMTPc_ERR_REP; 1603 | break; 1604 | } 1605 | 1606 | return (reply); 1607 | } 1608 | #endif 1609 | 1610 | /* 1611 | ********************************************************************************************************* 1612 | * SMTPc_MAIL() 1613 | * 1614 | * Description : (1) Build the MAIL command, send it to the server and validate reply. 1615 | * 1616 | * (a) Send command to the server 1617 | * (b) Receive server's reply and validate 1618 | * 1619 | * 1620 | * Argument(s) : sock_id Socket ID. 1621 | * from Argument of the "MAIL" command (sender mailbox). 1622 | * completion_code Numeric value returned by server indicating command status. 1623 | * perr Pointer to variable that will hold the return error code from this 1624 | * function : 1625 | * 1626 | * SMTPc_ERR_NONE No error. 1627 | * SMTPc_ERR_TX_FAILED Error querying server. 1628 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 1629 | * SMTPc_ERR_REP Error with reply. 1630 | * 1631 | * Return(s) : Complete reply from the server, if NO reception error. 1632 | * 1633 | * (CPU_CHAR *)0, otherwise. 1634 | * 1635 | * Caller(s) : SMTPc_SendMsg(). 1636 | * 1637 | * Note(s) : (2) From RFC #2821, "the MAIL command is used to initiate a mail transaction in which 1638 | * the mail data is delivered to an SMTP server [...]". 1639 | * 1640 | * (3) The server will send a 250 "Requested mail action okay, completed" reply upon 1641 | * success. A positive reply is the only reply that will lead to a "SMTPc_ERR_NONE" 1642 | * error return code. 1643 | * 1644 | * (4) This implementation will accept reply 250, as well as any other positive reply. 1645 | ********************************************************************************************************* 1646 | */ 1647 | 1648 | static CPU_CHAR *SMTPc_MAIL (NET_SOCK_ID sock_id, 1649 | CPU_CHAR *from, 1650 | CPU_INT32U *completion_code, 1651 | SMTPc_ERR *perr) 1652 | { 1653 | CPU_CHAR *reply; 1654 | CPU_SIZE_T len; 1655 | 1656 | /* ----------------- TX CMD TO SERVER ----------------- */ 1657 | Str_Copy(SMTPc_Comm_Buf, SMTPc_CMD_MAIL); 1658 | Str_Cat(SMTPc_Comm_Buf, " FROM:<"); 1659 | Str_Cat(SMTPc_Comm_Buf, from); 1660 | Str_Cat(SMTPc_Comm_Buf, ">\r\n"); 1661 | 1662 | len = Str_Len(SMTPc_Comm_Buf); 1663 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, len, perr); 1664 | if (*perr != SMTPc_ERR_NONE) { 1665 | *perr = SMTPc_ERR_TX_FAILED; 1666 | return ((CPU_CHAR *)0); 1667 | } 1668 | 1669 | /* ---------- RX SERVER'S RESPONSE & VALIDATE --------- */ 1670 | reply = SMTPc_RxReply(sock_id, perr); /* See Note #3. */ 1671 | if (*perr != SMTPc_ERR_NONE) { 1672 | *perr = SMTPc_ERR_RX_FAILED; 1673 | return ((CPU_CHAR *)0); 1674 | } 1675 | 1676 | 1677 | SMTPc_ParseReply(reply, completion_code, perr); /* See Note #4. */ 1678 | switch (*perr) { 1679 | case SMTPc_ERR_REP_POS: /* If any pos rep... */ 1680 | *perr = SMTPc_ERR_NONE; /* ... no err. */ 1681 | break; 1682 | 1683 | case SMTPc_ERR_REP_TOO_SHORT: 1684 | *perr = SMTPc_ERR_REP; 1685 | reply = (CPU_CHAR *)0; 1686 | break; 1687 | 1688 | default: 1689 | *perr = SMTPc_ERR_REP; 1690 | break; 1691 | } 1692 | 1693 | return (reply); 1694 | } 1695 | 1696 | 1697 | /* 1698 | ********************************************************************************************************* 1699 | * SMTPc_RCPT() 1700 | * 1701 | * Description : (1) Build the RCPT command, send it to the server and validate reply. 1702 | * 1703 | * (a) Send command to the server 1704 | * (b) Receive server's reply and validate 1705 | * 1706 | * 1707 | * Argument(s) : sock_id Socket ID. 1708 | * to Argument of the "RCPT" command (receiver mailbox). 1709 | * completion_code Numeric value returned by server indicating command status. 1710 | * perr Pointer to variable that will hold the return error code from this 1711 | * function : 1712 | * 1713 | * SMTPc_ERR_NONE No error. 1714 | * SMTPc_ERR_TX_FAILED Error querying server. 1715 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 1716 | * SMTPc_ERR_REP Error with reply. 1717 | * 1718 | * Return(s) : Complete reply from the server, if NO reception error. 1719 | * 1720 | * (CPU_CHAR *)0, otherwise. 1721 | * 1722 | * Caller(s) : SMTPc_SendMsg(). 1723 | * 1724 | * Note(s) : (2) From RFC #2821, "the RCPT command is used to identify an individual recipient of the 1725 | * mail data; multiple recipients are specified by multiple use of this command". 1726 | * 1727 | * (3) The server will send a 250 "Requested mail action okay, completed" or a 251 "User 1728 | * not local; will forwarded to " reply upon success. 1729 | * 1730 | * (4) This implementation will accept replies 250 and 251 as positive replies. Reply 551 1731 | * "User not local; please try " will result in an error. 1732 | ********************************************************************************************************* 1733 | */ 1734 | 1735 | static CPU_CHAR *SMTPc_RCPT (NET_SOCK_ID sock_id, 1736 | CPU_CHAR *to, 1737 | CPU_INT32U *completion_code, 1738 | SMTPc_ERR *perr) 1739 | { 1740 | CPU_CHAR *reply; 1741 | CPU_SIZE_T len; 1742 | 1743 | /* ----------------- TX CMD TO SERVER ----------------- */ 1744 | Str_Copy(SMTPc_Comm_Buf, SMTPc_CMD_RCPT); 1745 | Str_Cat(SMTPc_Comm_Buf, " TO:<"); 1746 | Str_Cat(SMTPc_Comm_Buf, to); 1747 | Str_Cat(SMTPc_Comm_Buf, ">\r\n"); 1748 | 1749 | len = Str_Len(SMTPc_Comm_Buf); 1750 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, len, perr); 1751 | if (*perr != SMTPc_ERR_NONE) { 1752 | *perr = SMTPc_ERR_TX_FAILED; 1753 | return ((CPU_CHAR *)0); 1754 | } 1755 | 1756 | /* ---------- RX SERVER'S RESPONSE & VALIDATE --------- */ 1757 | reply = SMTPc_RxReply(sock_id, perr); /* See Note #3. */ 1758 | if (*perr != SMTPc_ERR_NONE) { 1759 | *perr = SMTPc_ERR_RX_FAILED; 1760 | return ((CPU_CHAR *)0); 1761 | } 1762 | 1763 | SMTPc_ParseReply(reply, completion_code, perr); /* See Note #4. */ 1764 | switch (*perr) { 1765 | case SMTPc_ERR_REP_POS: 1766 | if ((*completion_code == SMTPc_REP_250) || 1767 | (*completion_code == SMTPc_REP_251)) { 1768 | *perr = SMTPc_ERR_NONE; 1769 | } else { 1770 | *perr = SMTPc_ERR_REP; 1771 | } 1772 | break; 1773 | 1774 | case SMTPc_ERR_REP_TOO_SHORT: 1775 | *perr = SMTPc_ERR_REP; 1776 | reply = (CPU_CHAR *)0; 1777 | break; 1778 | 1779 | default: 1780 | *perr = SMTPc_ERR_REP; 1781 | break; 1782 | } 1783 | 1784 | return (reply); 1785 | } 1786 | 1787 | 1788 | /* 1789 | ********************************************************************************************************* 1790 | * SMTPc_DATA() 1791 | * 1792 | * Description : (1) Build the DATA command, send it to the server and validate reply. 1793 | * 1794 | * (a) Send command to the server 1795 | * (b) Receive server's reply and validate 1796 | * 1797 | * 1798 | * Argument(s) : sock_id Socket ID. 1799 | * completion_code Numeric value returned by server indicating command status. 1800 | * perr Pointer to variable that will hold the return error code from this 1801 | * function : 1802 | * 1803 | * SMTPc_ERR_NONE No error. 1804 | * SMTPc_ERR_TX_FAILED Error querying server. 1805 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 1806 | * SMTPc_ERR_REP Error with reply. 1807 | * 1808 | * Return(s) : Complete reply from the server, if NO reception error. 1809 | * 1810 | * (CPU_CHAR *)0, otherwise. 1811 | * 1812 | * Caller(s) : SMTPc_SendMsg(). 1813 | * 1814 | * Note(s) : (2) The DATA command is used to indicate to the SMTP server that all the following lines 1815 | * up to but not including the end of mail data indicator are to be considered as the 1816 | * message text. 1817 | * 1818 | * (3) The receiver normally sends a 354 "Start mail input" reply and then treats the lines 1819 | * following the command as mail data from the sender. 1820 | ********************************************************************************************************* 1821 | */ 1822 | 1823 | static CPU_CHAR *SMTPc_DATA (NET_SOCK_ID sock_id, 1824 | CPU_INT32U *completion_code, 1825 | SMTPc_ERR *perr) 1826 | { 1827 | CPU_CHAR *reply; 1828 | CPU_SIZE_T len; 1829 | 1830 | /* ----------------- TX CMD TO SERVER ----------------- */ 1831 | Str_Copy(SMTPc_Comm_Buf, SMTPc_CMD_DATA); 1832 | Str_Cat(SMTPc_Comm_Buf, "\r\n"); 1833 | 1834 | 1835 | len = Str_Len(SMTPc_Comm_Buf); 1836 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, len, perr); 1837 | if (*perr != SMTPc_ERR_NONE) { 1838 | *perr = SMTPc_ERR_TX_FAILED; 1839 | return ((CPU_CHAR *)0); 1840 | } 1841 | 1842 | /* ---------- RX SERVER'S RESPONSE & VALIDATE --------- */ 1843 | reply = SMTPc_RxReply(sock_id, perr); /* See Note #3. */ 1844 | if (*perr != SMTPc_ERR_NONE) { 1845 | *perr = SMTPc_ERR_RX_FAILED; 1846 | return ((CPU_CHAR *)0); 1847 | } 1848 | 1849 | SMTPc_ParseReply(reply, completion_code, perr); 1850 | switch (*perr) { 1851 | case SMTPc_ERR_REP_INTER: 1852 | if (*completion_code == SMTPc_REP_354) { 1853 | *perr = SMTPc_ERR_NONE; 1854 | } else { 1855 | *perr = SMTPc_ERR_REP; 1856 | } 1857 | break; 1858 | 1859 | case SMTPc_ERR_REP_TOO_SHORT: 1860 | *perr = SMTPc_ERR_REP; 1861 | reply = (CPU_CHAR *)0; 1862 | break; 1863 | 1864 | default: 1865 | *perr = SMTPc_ERR_REP; 1866 | break; 1867 | } 1868 | 1869 | return (reply); 1870 | } 1871 | 1872 | 1873 | /* 1874 | ********************************************************************************************************* 1875 | * SMTPc_RSET() 1876 | * 1877 | * Description : (1) Build the RSET command, send it to the server and validate reply. 1878 | * 1879 | * (a) Send command to the server 1880 | * (b) Receive server's reply and validate 1881 | * 1882 | * 1883 | * Argument(s) : sock_id Socket ID. 1884 | * completion_code Numeric value returned by server indicating command status. 1885 | * perr Pointer to variable that will hold the return error code from this 1886 | * function : 1887 | * 1888 | * SMTPc_ERR_NONE No error. 1889 | * SMTPc_ERR_TX_FAILED Error querying server. 1890 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 1891 | * SMTPc_ERR_REP Error with reply. 1892 | * 1893 | * Return(s) : Complete reply from the server, if NO reception error. 1894 | * 1895 | * (CPU_CHAR *)0, otherwise. 1896 | * 1897 | * Caller(s) : SMTPc_SendMsg(). 1898 | * 1899 | * Note(s) : (2) From RFC #2821, "the RSET command specifies that the current mail transaction will 1900 | * be aborted. Any stored sender, recipients, and mail data MUST be discarded, and all 1901 | * buffers and state tables cleared". 1902 | * 1903 | * (3) The server MUST send a 250 "Requested mail action okay, completed" reply to a RSET 1904 | * command with no arguments. 1905 | ********************************************************************************************************* 1906 | */ 1907 | 1908 | static CPU_CHAR *SMTPc_RSET (NET_SOCK_ID sock_id, 1909 | CPU_INT32U *completion_code, 1910 | SMTPc_ERR *perr) 1911 | { 1912 | CPU_CHAR *reply; 1913 | CPU_SIZE_T len; 1914 | 1915 | /* ----------------- TX CMD TO SERVER ----------------- */ 1916 | Str_Copy(SMTPc_Comm_Buf, SMTPc_CMD_RSET); 1917 | Str_Cat(SMTPc_Comm_Buf, "\r\n"); 1918 | 1919 | len = Str_Len(SMTPc_Comm_Buf); 1920 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, len, perr); 1921 | if (*perr != SMTPc_ERR_NONE) { 1922 | *perr = SMTPc_ERR_TX_FAILED; 1923 | return ((CPU_CHAR *)0); 1924 | } 1925 | 1926 | /* ---------- RX SERVER'S RESPONSE & VALIDATE --------- */ 1927 | reply = SMTPc_RxReply(sock_id, perr); /* See Note #3. */ 1928 | if (*perr != SMTPc_ERR_NONE) { 1929 | *perr = SMTPc_ERR_RX_FAILED; 1930 | return ((CPU_CHAR *)0); 1931 | } 1932 | 1933 | SMTPc_ParseReply(reply, completion_code, perr); 1934 | switch (*perr) { 1935 | case SMTPc_ERR_REP_POS: 1936 | if (*completion_code == SMTPc_REP_250) { 1937 | *perr = SMTPc_ERR_NONE; 1938 | } else { 1939 | *perr = SMTPc_ERR_REP; 1940 | } 1941 | break; 1942 | 1943 | case SMTPc_ERR_REP_TOO_SHORT: 1944 | *perr = SMTPc_ERR_REP; 1945 | reply = (CPU_CHAR *)0; 1946 | break; 1947 | 1948 | default: 1949 | *perr = SMTPc_ERR_REP; 1950 | break; 1951 | } 1952 | 1953 | return (reply); 1954 | } 1955 | 1956 | 1957 | /* 1958 | ********************************************************************************************************* 1959 | * SMTPc_QUIT() 1960 | * 1961 | * Description : (1) Build the QUIT command, send it to the server and validate reply. 1962 | * 1963 | * (a) Send command to the server 1964 | * (b) Receive server's reply and validate 1965 | * 1966 | * 1967 | * Argument(s) : sock_id Socket ID. 1968 | * completion_code Numeric value returned by server indicating command status. 1969 | * perr Pointer to variable that will hold the return error code from this 1970 | * function : 1971 | * 1972 | * SMTPc_ERR_NONE No error. 1973 | * SMTPc_ERR_TX_FAILED Error querying server. 1974 | * SMTPc_ERR_RX_FAILED Error receiving server reply. 1975 | * SMTPc_ERR_REP Error with reply. 1976 | * 1977 | * Return(s) : Complete reply from the server, if NO reception error. 1978 | * 1979 | * (CPU_CHAR *)0, otherwise. 1980 | * 1981 | * Caller(s) : SMTPc_Disconnect(). 1982 | * 1983 | * Note(s) : (2) From RFC #2821, "the QUIT command specifies that the receiver MUST send an OK reply, 1984 | * and then close the transmission channel. The receiver MUST NOT intentionally close 1985 | * the transmission channel until it receives and replies to a QUIT command (even if 1986 | * there was an error). the sender MUST NOT intentionally close the transmission 1987 | * channel until it sends a QUIT command and SHOULD wait until it receives the reply 1988 | * (even if there was an error response to a previous command)". 1989 | * 1990 | * (3) The server MUST send a 221 "Service closing transmission channel" reply to a QUIT 1991 | * command. 1992 | ********************************************************************************************************* 1993 | */ 1994 | 1995 | static CPU_CHAR *SMTPc_QUIT (NET_SOCK_ID sock_id, 1996 | CPU_INT32U *completion_code, 1997 | SMTPc_ERR *perr) 1998 | { 1999 | CPU_CHAR *reply; 2000 | CPU_SIZE_T len; 2001 | 2002 | /* ----------------- TX CMD TO SERVER ----------------- */ 2003 | Str_Copy(SMTPc_Comm_Buf, SMTPc_CMD_QUIT); 2004 | Str_Cat(SMTPc_Comm_Buf, "\r\n"); 2005 | len = Str_Len(SMTPc_Comm_Buf); 2006 | 2007 | SMTPc_QueryServer(sock_id, SMTPc_Comm_Buf, len, perr); 2008 | if (*perr != SMTPc_ERR_NONE) { 2009 | *perr = SMTPc_ERR_TX_FAILED; 2010 | return ((CPU_CHAR *)0); 2011 | } 2012 | 2013 | /* ---------- RX SERVER'S RESPONSE & VALIDATE --------- */ 2014 | reply = SMTPc_RxReply(sock_id, perr); /* See Note #3. */ 2015 | if (*perr != SMTPc_ERR_NONE) { 2016 | *perr = SMTPc_ERR_RX_FAILED; 2017 | return ((CPU_CHAR *)0); 2018 | } 2019 | 2020 | SMTPc_ParseReply(reply, completion_code, perr); 2021 | switch (*perr) { 2022 | case SMTPc_ERR_REP_POS: 2023 | if (*completion_code == SMTPc_REP_221) { 2024 | *perr = SMTPc_ERR_NONE; 2025 | } else { 2026 | *perr = SMTPc_ERR_REP; 2027 | } 2028 | break; 2029 | 2030 | case SMTPc_ERR_REP_TOO_SHORT: 2031 | *perr = SMTPc_ERR_REP; 2032 | reply = (CPU_CHAR *)0; 2033 | break; 2034 | 2035 | default: 2036 | *perr = SMTPc_ERR_REP; 2037 | break; 2038 | } 2039 | 2040 | return (reply); 2041 | } 2042 | -------------------------------------------------------------------------------- /Source/smtp-c.h: -------------------------------------------------------------------------------- 1 | /* 2 | ********************************************************************************************************* 3 | * uC/SMTPc 4 | * Simple Mail Transfer Protocol (client) 5 | * 6 | * Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com 7 | * 8 | * SPDX-License-Identifier: APACHE-2.0 9 | * 10 | * This software is subject to an open source license and is distributed by 11 | * Silicon Laboratories Inc. pursuant to the terms of the Apache License, 12 | * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. 13 | * 14 | ********************************************************************************************************* 15 | */ 16 | 17 | /* 18 | ********************************************************************************************************* 19 | * 20 | * SMTP CLIENT 21 | * 22 | * Filename : smtp-c.h 23 | * Version : V2.01.01 24 | ********************************************************************************************************* 25 | * Note(s) : (1) This code implements a subset of the SMTP protocol (RFC 2821). More precisely, the 26 | * following commands have been implemented: 27 | * 28 | * HELO 29 | * AUTH (if enabled) 30 | * MAIL 31 | * RCPT 32 | * DATA 33 | * RSET 34 | * NOOP 35 | * QUIT 36 | ********************************************************************************************************* 37 | */ 38 | 39 | 40 | /* 41 | ********************************************************************************************************* 42 | * MODULE 43 | * 44 | * Note(s) : (1) This header file is protected from multiple preprocessor inclusion through use of the 45 | * SMTPc present preprocessor macro definition. 46 | ********************************************************************************************************* 47 | */ 48 | 49 | #ifndef SMTPc_PRESENT /* See Note #1. */ 50 | #define SMTPc_PRESENT 51 | 52 | 53 | /* 54 | ********************************************************************************************************* 55 | * SMTPc VERSION NUMBER 56 | * 57 | * Note(s) : (1) (a) The SMTPc module software version is denoted as follows : 58 | * 59 | * Vx.yy.zz 60 | * 61 | * where 62 | * V denotes 'Version' label 63 | * x denotes major software version revision number 64 | * yy denotes minor software version revision number 65 | * zz denotes sub-minor software version revision number 66 | * 67 | * (b) The SMTPc software version label #define is formatted as follows : 68 | * 69 | * ver = x.yyzz * 100 * 100 70 | * 71 | * where 72 | * ver denotes software version number scaled as an integer value 73 | * x.yyzz denotes software version number, where the unscaled integer 74 | * portion denotes the major version number & the unscaled 75 | * fractional portion denotes the (concatenated) minor 76 | * version numbers 77 | ********************************************************************************************************* 78 | */ 79 | 80 | #define SMTPc_VERSION 20101u /* See Note #1. */ 81 | 82 | 83 | /* 84 | ********************************************************************************************************* 85 | * EXTERNS 86 | ********************************************************************************************************* 87 | */ 88 | 89 | #ifdef SMTPc_MODULE 90 | #define SMTPc_EXT 91 | #else 92 | #define SMTPc_EXT extern 93 | #endif 94 | 95 | 96 | /* 97 | ********************************************************************************************************* 98 | * INCLUDE FILES 99 | * 100 | * Note(s) : (1) The SMTPc module files are located in the following directories : 101 | * 102 | * (a) \\smtp-c_cfg.h 103 | * 104 | * (b) (1) \\Source\net_*.* 105 | * 106 | * (2) If network security manager is to be used: 107 | * 108 | * (A) \\Secure\net_secure_mgr.* 109 | * 110 | * (B) \\Secure\\net_secure.* 111 | * 112 | * (c) \\Source\smtp-c.h 113 | * \smtp-c.c 114 | * 115 | * where 116 | * directory path for Your Product's Application 117 | * directory path for network protocol suite 118 | * directory path for SMTPc module 119 | * 120 | * (2) CPU-configuration software files are located in the following directories : 121 | * 122 | * (a) \\cpu_*.* 123 | * (b) \\\\cpu*.* 124 | * 125 | * where 126 | * directory path for common CPU-compiler software 127 | * directory name for specific processor (CPU) 128 | * directory name for specific compiler 129 | * 130 | * (3) NO compiler-supplied standard library functions SHOULD be used. 131 | * 132 | * (a) Standard library functions are implemented in the custom library module(s) : 133 | * 134 | * \\lib_*.* 135 | * 136 | * where 137 | * directory path for custom library software 138 | * 139 | * (b) #### The reference to standard library header files SHOULD be removed once all custom 140 | * library functions are implemented WITHOUT reference to ANY standard library function(s). 141 | * 142 | * (4) Compiler MUST be configured to include as additional include path directories : 143 | * 144 | * (a) '\\' directory See Note #1a 145 | * 146 | * (b) (1) '\\ See Note #1b1 147 | * 148 | * (2) (A) '\\Secure\' See Note #1b2A 149 | * (B) '\\Secure\\' See Note #1b2B 150 | * 151 | * (c) '\\' directory See Note #1c 152 | * 153 | * (d) (1) '\\' directory See Note #2a 154 | * (2) '\\\\' directory See Note #2b 155 | * 156 | * (e) '\\' directory See Note #3a 157 | ********************************************************************************************************* 158 | */ 159 | 160 | #include /* CPU Configuration (see Note #2b) */ 161 | #include /* CPU Core Library (see Note #2a) */ 162 | 163 | #include /* Standard Defines (see Note #3a) */ 164 | #include /* Standard String Library (see Note #3a) */ 165 | 166 | 167 | #include /* Network Protocol Suite (see Note #1b) */ 168 | #include 169 | #include 170 | #include 171 | #include 172 | #include 173 | #include 174 | #include 175 | 176 | 177 | #if 1 /* See Note #3b. */ 178 | #include 179 | #endif 180 | 181 | 182 | /* 183 | ********************************************************************************************************* 184 | * DEFINES 185 | ********************************************************************************************************* 186 | */ 187 | 188 | /* 189 | ********************************************************************************************************* 190 | * ERROR CODES DEFINES 191 | ********************************************************************************************************* 192 | */ 193 | typedef enum smtpc_err { 194 | SMTPc_ERR_NONE = 51000u, 195 | SMTPc_ERR_SOCK_OPEN_FAILED = 51001u, 196 | SMTPc_ERR_SOCK_CONN_FAILED = 51002u, 197 | SMTPc_ERR_NO_SMTP_SERV = 51003u, 198 | SMTPc_ERR_RX_FAILED = 51004u, 199 | SMTPc_ERR_TX_FAILED = 51005u, 200 | SMTPc_ERR_NULL_ARG = 51006u, 201 | SMTPc_ERR_LINE_TOO_LONG = 51007u, 202 | SMTPc_ERR_STR_TOO_LONG = 51008u, 203 | SMTPc_ERR_REP = 51009u, 204 | SMTPc_ERR_BUF_TOO_SMALL = 51010u, 205 | SMTPc_ERR_ENCODE = 51011u, 206 | SMTPc_ERR_AUTH_FAILED = 51012u, 207 | SMTPc_ERR_SECURE_NOT_AVAIL = 51013u, 208 | 209 | SMTPc_ERR_REP_POS = 51000u, 210 | SMTPc_ERR_REP_INTER = 51013u, 211 | SMTPc_ERR_REP_NEG = 51014u, 212 | SMTPc_ERR_REP_TOO_SHORT = 51015u, 213 | 214 | SMTPc_ERR_INVALID_ADDR = 51016u, 215 | 216 | } SMTPc_ERR; 217 | 218 | 219 | /* 220 | ********************************************************************************************************* 221 | * SMTPc STRUCT DEFINES 222 | * 223 | * Note(s) : (1) Line length limit, as defined in RFC #2822. 224 | * 225 | * (2) SMTPc_CFG_COMM_BUF_LEN is the length of the buffer used to receive replies from the SMTP 226 | * server. As stated in RFC #2821, Section 'The SMTP Specifications, Additional Implementation 227 | * Issues, Sizes and Timeouts, Size limits and minimums', "The maximum total length of a 228 | * reply code and the is 512 characters". 229 | * 230 | * This buffer is also used to build outgoing messages and MUST NOT be smaller than 1000 231 | * (see Note #1). 232 | * 233 | * (3) Maximum length of key-value strings in structure SMTPc_KEY_VAL. 234 | * 235 | * (4) As mentioned in RFC #2821, Section 'The SMTP Specifications, Additional 236 | * Implementation Issues, Sizes and Timeouts, Size limits and minimums', "The maximum 237 | * total length of a user name or other local-part is 64 characters [and] the maximum 238 | * total length of a domain name or number is 255 characters.". Adding 2 for 239 | * '@' (see SMTPc_MBOX structure) and '\0'. 240 | * 241 | * (5) Maximum length of content-type. 242 | * 243 | * (6) From RFC #2822, Section 'Syntax, Fields definitions, Identification fields', "The message 244 | * identifier (msg-id) [field] is similar in syntax to an angle-addr construct". 245 | * 246 | * (7) Size of ParamArray in structure SMTPc_MIME_ENTITY_HDR. 247 | * 248 | * (8) Maximum length of attachment's name and description. 249 | ********************************************************************************************************* 250 | */ 251 | 252 | #define SMTPc_LINE_LEN_LIM 1000 /* See Note #1. */ 253 | 254 | #define SMTPc_COMM_BUF_LEN 1024 /* See Note #2. */ 255 | 256 | /* See Note #3. */ 257 | #define SMTPc_KEY_VAL_KEY_LEN 30 258 | #define SMTPc_KEY_VAL_VAL_LEN 30 259 | 260 | /* See Note #4. */ 261 | #define SMTPc_MBOX_DOMAIN_NAME_LEN 255 262 | #define SMTPc_MBOX_LOCAL_PART_LEN 64 263 | #define SMTPc_MBOX_ADDR_LEN (SMTPc_MBOX_DOMAIN_NAME_LEN + SMTPc_MBOX_LOCAL_PART_LEN + 2) 264 | 265 | /* See Note #5. */ 266 | #define SMTPc_MIME_CONTENT_TYPE_LEN 20 267 | 268 | /* See Note #6. */ 269 | #define SMTPc_MIME_ID_LEN SMTPc_MBOX_ADDR_LEN 270 | 271 | /* See Note #7. */ 272 | #define SMTPc_MIME_MAX_KEYVAL 1 273 | 274 | /* See Note #8. */ 275 | #define SMTPc_ATTACH_NAME_LEN 50 276 | #define SMTPc_ATTACH_DESC_LEN 50 277 | 278 | /* See Note #6. */ 279 | #define SMTPc_MSG_MSGID_LEN SMTPc_MBOX_ADDR_LEN 280 | 281 | 282 | 283 | /* 284 | ********************************************************************************************************* 285 | * STATUS CODES DEFINES 286 | * 287 | * Note(s): (1) Reply codes are defined here and classified by category. Note that this list is not meant 288 | * to be exhaustive. 289 | ********************************************************************************************************* 290 | */ 291 | 292 | /* ------------ POSITIVE PRELIMINARY REPLY ------------ */ 293 | #define SMTPc_REP_POS_PRELIM_GRP 1 294 | 295 | /* ------------ POSITIVE COMPLETION REPLY ------------- */ 296 | #define SMTPc_REP_POS_COMPLET_GRP 2 297 | #define SMTPc_REP_220 220 /* Service ready. */ 298 | #define SMTPc_REP_221 221 /* Service closing transmission channel. */ 299 | #define SMTPc_REP_235 235 /* Authentication successful. */ 300 | #define SMTPc_REP_250 250 /* Requested mail action okay, completed. */ 301 | #define SMTPc_REP_251 251 /* User not local; will forward to . */ 302 | 303 | /* ------------ POSITIVE INTERMEDIATE REPLY ----------- */ 304 | #define SMTPc_REP_POS_INTER_GRP 3 305 | #define SMTPc_REP_354 354 /* Start mail input; end with .. */ 306 | 307 | /* -------- TRANSIENT NEGATIVE COMPLETION REPLY ------- */ 308 | #define SMTPc_REP_NEG_TRANS_COMPLET_GRP 4 309 | #define SMTPc_REP_421 421 /* Service closing transmission channel. */ 310 | 311 | /* -------- PERMANENT NEGATIVE COMPLETION REPLY ------- */ 312 | #define SMTPc_REP_NEG_COMPLET_GRP 5 313 | #define SMTPc_REP_503 503 /* Bad sequence of commands. */ 314 | #define SMTPc_REP_504 504 /* Command parameter not implemented. */ 315 | #define SMTPc_REP_535 535 /* Authentication failure. */ 316 | #define SMTPc_REP_550 550 /* Requested action not taken: mailbox unavailable. */ 317 | #define SMTPc_REP_554 554 /* Transaction failed. */ 318 | 319 | 320 | /* 321 | ********************************************************************************************************* 322 | * COMMANDS AND STRINGS DEFINES 323 | ********************************************************************************************************* 324 | */ 325 | 326 | #define SMTPc_CMD_HELO "HELO" 327 | #define SMTPc_CMD_MAIL "MAIL" 328 | #define SMTPc_CMD_RCPT "RCPT" 329 | #define SMTPc_CMD_DATA "DATA" 330 | #define SMTPc_CMD_RSET "RSET" 331 | #define SMTPc_CMD_NOOP "NOOP" 332 | #define SMTPc_CMD_QUIT "QUIT" 333 | 334 | #define SMTPc_CMD_AUTH "AUTH" 335 | #define SMTPc_CMD_AUTH_MECHANISM_PLAIN "PLAIN" 336 | 337 | 338 | #define SMTPc_CRLF "\x0D\x0A" 339 | #define SMTPc_EOM "\x0D\x0A.\x0D\x0A" 340 | #define SMTPc_CRLF_SIZE 2u 341 | 342 | #define SMTPc_HDR_FROM "From: " 343 | #define SMTPc_HDR_SENDER "Sender: " 344 | #define SMTPc_HDR_TO "To: " 345 | #define SMTPc_HDR_REPLYTO "Reply-to: " 346 | #define SMTPc_HDR_CC "Cc: " 347 | #define SMTPc_HDR_SUBJECT "Subject: " 348 | 349 | #define SMTPc_TAG_IPv6 "IPv6:" 350 | 351 | 352 | /* 353 | ********************************************************************************************************* 354 | * BASE 64 ENCODER DEFINES 355 | * 356 | * Note(s) : (1) The maximum input buffer passed to the base 64 encoder depends of the configured maximum 357 | * lengths for the username and password. Two additional characters are added to these 358 | * values to account for the delimiter (see 'smtp-c.c SMTPc_AUTH() Note #2'). 359 | * 360 | * (2) The size of the output buffer the base 64 encoder produces is typically bigger than the 361 | * input buffer by a factor of (4 x 3). However, when padding is necessary, up to 3 362 | * additional characters could by appended. Finally, one more character is used to NULL 363 | * terminate the buffer. 364 | ********************************************************************************************************* 365 | */ 366 | 367 | #define SMTPc_ENCODER_BASE64_DELIMITER_CHAR 0 368 | /* See Note #1. */ 369 | #define SMTPc_ENCODER_BASE54_IN_MAX_LEN (SMTPc_CFG_MBOX_NAME_DISP_LEN + SMTPc_CFG_MSG_SUBJECT_LEN + 2) 370 | 371 | /* See Note #2. */ 372 | #define SMTPc_ENCODER_BASE64_OUT_MAX_LEN ((((SMTPc_CFG_MBOX_NAME_DISP_LEN + SMTPc_CFG_MSG_SUBJECT_LEN + 2) * 4) / 3) + 4) 373 | 374 | 375 | /* 376 | ********************************************************************************************************* 377 | * DATA TYPES 378 | * 379 | * Note(s): (1) From RFC #2821 'The SMTP Model, Terminology, Mail Objects', "SMTP transports a mail 380 | * object. A mail object contains an envelope and content. The SMTP content is sent 381 | * in the SMTP DATA protocol unit and has two parts: the headers and the body": 382 | * 383 | * |----------------------| 384 | * | | 385 | * | | Envelope 386 | * | | 387 | * |======================| 388 | * | | 389 | * | Headers | 390 | * | | 391 | * | | 392 | * | | 393 | * |----------------------| Content 394 | * | | 395 | * | Body | 396 | * | | 397 | * | | 398 | * | | 399 | * |----------------------| 400 | * 401 | ********************************************************************************************************* 402 | */ 403 | 404 | /* 405 | ********************************************************************************************************* 406 | * KEY-VALUE STRUCT DATA TYPES 407 | * 408 | * Note(s): (1) This structure makes room for additional MIME header fields (see RFC #2045, Section 409 | * 'Additional MIME Header Fields'). 410 | ********************************************************************************************************* 411 | */ 412 | 413 | typedef struct SMTPc_key_val 414 | { 415 | CPU_CHAR Key[SMTPc_KEY_VAL_KEY_LEN]; /* Key (hdr field name). */ 416 | CPU_CHAR Val[SMTPc_KEY_VAL_VAL_LEN]; /* Val associated with the preceding key. */ 417 | } SMTPc_KEY_VAL; 418 | 419 | 420 | /* 421 | ********************************************************************************************************* 422 | * SMTP MAILBOX AND MAILBOX LIST DATA TYPES 423 | * 424 | * Note(s): (1) Structure representing an email address, as well as the name of its owner. 425 | ********************************************************************************************************* 426 | */ 427 | 428 | typedef struct SMTPc_mbox 429 | { 430 | CPU_CHAR NameDisp[SMTPc_CFG_MBOX_NAME_DISP_LEN]; /* Disp'd name of addr's owner. */ 431 | CPU_CHAR Addr [SMTPc_MBOX_ADDR_LEN]; /* Addr (local part '@' domain). */ 432 | } SMTPc_MBOX; 433 | 434 | 435 | /* 436 | ********************************************************************************************************* 437 | * SMTP MIME ENTITY HEADER 438 | * 439 | * Note(s): (1) See RFC #2045 for details. 440 | * 441 | * (2) Structure subject to change. For instance, other data structures could be used to represent 442 | * "Encoding", etc. The encoding could also be left to do by the application 443 | ********************************************************************************************************* 444 | */ 445 | 446 | typedef struct SMTPc_mime_entity_hdr 447 | { 448 | CPU_CHAR *ContentType[SMTPc_MIME_CONTENT_TYPE_LEN]; /* Description of contained body data (IANA assigned). */ 449 | SMTPc_KEY_VAL *ParamArray[SMTPc_MIME_MAX_KEYVAL]; /* Additional param for specified content-type. */ 450 | void *ContentEncoding; /* Content transfer encoding. */ 451 | void (*EncodingFnctPtr)(CPU_CHAR *, /* Ptr to fnct performing the encoding of the */ 452 | NET_ERR *); /* attachment. */ 453 | CPU_CHAR ID[SMTPc_MIME_ID_LEN]; /* Unique attachment id. */ 454 | } SMTPc_MIME_ENTITY_HDR; 455 | 456 | 457 | /* 458 | ********************************************************************************************************* 459 | * SMTP MESSAGE ATTACHMENT AND ATTACHMENT LIST DATA TYPES 460 | * 461 | * Note(s): (1) Attachments are not going to be supported in the first version of the uCSMTPc module. 462 | * Hence, the format of this structure will surely change to accommodate for possible 463 | * file system access. 464 | ********************************************************************************************************* 465 | */ 466 | 467 | typedef struct SMTPc_attach 468 | { 469 | SMTPc_MIME_ENTITY_HDR MIMEPartHdrStruct; /* MIME content hdr for this attachment. */ 470 | CPU_CHAR Name[SMTPc_ATTACH_NAME_LEN]; /* Name of attachment inserted in the message. */ 471 | CPU_CHAR Desc[SMTPc_ATTACH_DESC_LEN]; /* Optional attachment description. */ 472 | void *AttachData; /* Ptr to beginning of body (data of the entity). */ 473 | CPU_INT32U Size ; /* Size of data in octets. */ 474 | 475 | } SMTPc_ATTACH; 476 | 477 | 478 | /* 479 | ********************************************************************************************************* 480 | * SMTP MSG Structure 481 | * 482 | * Note(s): (1) A mail object is represented in this module by the structure SMTPc_MSG. This 483 | * structure contains all the necessary information to generate the mail object 484 | * and to send it to the SMTP server. More specifically, it encapsulates the various 485 | * addresses of the sender and recipients, MIME information, the message itself, and 486 | * finally the eventual attachments. 487 | ********************************************************************************************************* 488 | */ 489 | 490 | typedef struct SMTPc_msg 491 | { 492 | SMTPc_MBOX *From; /* "From" field (1:1). */ 493 | SMTPc_MBOX *ToArray[SMTPc_CFG_MSG_MAX_TO]; /* "To" field (1:*). */ 494 | SMTPc_MBOX *ReplyTo; /* "Reply-to" field (0:1). */ 495 | SMTPc_MBOX *Sender; /* "Sender" field (0:1). */ 496 | SMTPc_MBOX *CCArray[SMTPc_CFG_MSG_MAX_CC]; /* "CC" field (0:*). */ 497 | SMTPc_MBOX *BCCArray[SMTPc_CFG_MSG_MAX_BCC]; /* "BCC" field (0:*). */ 498 | CPU_CHAR MsgID[SMTPc_MSG_MSGID_LEN]; /* Unique msg id. */ 499 | SMTPc_MIME_ENTITY_HDR MIMEMsgHdrStruct; /* Mail obj MIME content headers. */ 500 | CPU_CHAR *Subject; /* Subject of msg. */ 501 | /* List of attachment(s), if any. */ 502 | SMTPc_ATTACH *AttachArray[SMTPc_CFG_MSG_MAX_ATTACH]; 503 | CPU_CHAR *ContentBodyMsg; /* Data of the mail obj content's body. */ 504 | CPU_INT32U ContentBodyMsgLen; /* Size (in octets) of buf pointed by ContentBodyMsg. */ 505 | } SMTPc_MSG; 506 | 507 | 508 | /* 509 | ********************************************************************************************************* 510 | * GLOBAL VARIABLES 511 | ********************************************************************************************************* 512 | */ 513 | 514 | SMTPc_EXT CPU_CHAR SMTPc_Comm_Buf[SMTPc_COMM_BUF_LEN]; 515 | 516 | 517 | /* 518 | ********************************************************************************************************* 519 | * FUNCTION PROTOTYPES 520 | ********************************************************************************************************* 521 | */ 522 | 523 | void SMTPc_SendMail (CPU_CHAR *p_host_name, 524 | CPU_INT16U port, 525 | CPU_CHAR *p_username, 526 | CPU_CHAR *p_pwd, 527 | NET_APP_SOCK_SECURE_CFG *p_secure_cfg, 528 | SMTPc_MSG *p_msg, 529 | SMTPc_ERR *p_err); 530 | 531 | /* ---------------- SMTP SESSION FNCTS ---------------- */ 532 | NET_SOCK_ID SMTPc_Connect (CPU_CHAR *p_host_name, 533 | CPU_INT16U port, 534 | CPU_CHAR *p_username, 535 | CPU_CHAR *p_pwd, 536 | NET_APP_SOCK_SECURE_CFG *p_secure_cfg, 537 | SMTPc_ERR *p_err); 538 | 539 | 540 | void SMTPc_SendMsg (NET_SOCK_ID sock_id, 541 | SMTPc_MSG *msg, 542 | SMTPc_ERR *perr); 543 | 544 | void SMTPc_Disconnect (NET_SOCK_ID sock_id, 545 | SMTPc_ERR *perr); 546 | 547 | 548 | /* -------------------- UTIL FNCTS -------------------- */ 549 | void SMTPc_SetMbox (SMTPc_MBOX *mbox, 550 | CPU_CHAR *name, 551 | CPU_CHAR *addr, 552 | SMTPc_ERR *perr); 553 | 554 | void SMTPc_SetMsg (SMTPc_MSG *msg, 555 | SMTPc_ERR *perr); 556 | 557 | 558 | /* 559 | ********************************************************************************************************* 560 | * TRACING 561 | ********************************************************************************************************* 562 | */ 563 | /* Trace level, default to TRACE_LEVEL_OFF */ 564 | #ifndef TRACE_LEVEL_OFF 565 | #define TRACE_LEVEL_OFF 0 566 | #endif 567 | 568 | #ifndef TRACE_LEVEL_INFO 569 | #define TRACE_LEVEL_INFO 1 570 | #endif 571 | 572 | #ifndef TRACE_LEVEL_DBG 573 | #define TRACE_LEVEL_DBG 2 574 | #endif 575 | 576 | #ifndef SMTPc_TRACE_LEVEL 577 | #define SMTPc_TRACE_LEVEL TRACE_LEVEL_OFF 578 | #endif 579 | 580 | #ifndef SMTPc_TRACE 581 | #define SMTPc_TRACE printf 582 | #endif 583 | 584 | #if ((defined(SMTPc_TRACE)) && \ 585 | (defined(SMTPc_TRACE_LEVEL)) && \ 586 | (SMTPc_TRACE_LEVEL >= TRACE_LEVEL_INFO) ) 587 | 588 | #if (SMTPc_TRACE_LEVEL >= TRACE_LEVEL_DBG) 589 | #define SMTPc_TRACE_DBG(msg) SMTPc_TRACE msg 590 | #else 591 | #define SMTPc_TRACE_DBG(msg) 592 | #endif 593 | 594 | #define SMTPc_TRACE_INFO(msg) SMTPc_TRACE msg 595 | 596 | #else 597 | #define SMTPc_TRACE_DBG(msg) 598 | #define SMTPc_TRACE_INFO(msg) 599 | #endif 600 | 601 | 602 | /* 603 | ********************************************************************************************************* 604 | * CONFIGURATION ERRORS 605 | ********************************************************************************************************* 606 | */ 607 | 608 | #ifndef SMTPc_CFG_IPPORT 609 | #error "SMTPc_CFG_IPPORT not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 610 | #endif 611 | 612 | 613 | #ifndef SMTPc_CFG_IPPORT_SECURE 614 | #error "SMTPc_CFG_IPPORT_SECURE not #define'd in 'smtp-c_cfg.h'see template file in package named 'smtp-c_cfg.h'" 615 | #endif 616 | 617 | 618 | #ifndef SMTPc_CFG_MAX_CONN_REQ_TIMEOUT_MS 619 | #error "SMTPc_CFG_MAX_CONN_REQ_TIMEOUT_MS not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 620 | #endif 621 | 622 | 623 | #ifndef SMTPc_CFG_MAX_CONN_CLOSE_TIMEOUT_MS 624 | #error "SMTPc_CFG_MAX_CONN_CLSOE_TIMEOUT_MS not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 625 | #endif 626 | 627 | 628 | #ifndef SMTPc_CFG_AUTH_EN 629 | #error "SMTPc_CFG_AUTH_EN not #define'd in 'smtp-c_cfg.h [MUST be DEF_DISABLED || DEF_ENABLED]" 630 | #elif ((SMTPc_CFG_AUTH_EN != DEF_DISABLED) && \ 631 | (SMTPc_CFG_AUTH_EN != DEF_ENABLED )) 632 | #error "SMTPc_CFG_AUTH_EN illegally #define'd in 'smtp-c_cfg.h' [MUST be DEF_DISABLED || DEF_ENABLED]" 633 | #endif 634 | 635 | 636 | #ifndef SMTPc_CFG_USERNAME_MAX_LEN 637 | #error "SMTPc_CFG_USERNAME_MAX_LEN not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 638 | #elif ((SMTPc_CFG_USERNAME_MAX_LEN < 0) || \ 639 | (SMTPc_CFG_USERNAME_MAX_LEN > DEF_INT_08U_MAX_VAL)) 640 | #error "SMTPc_CFG_USERNAME_MAX_LEN illegally #define'd in 'smtp-c_cfg.h'[MUST be >= 0 && <= 255]" 641 | #endif 642 | 643 | 644 | #ifndef SMTPc_CFG_PW_MAX_LEN 645 | #error "SMTPc_CFG_PW_MAX_LEN not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 646 | #elif ((SMTPc_CFG_PW_MAX_LEN < 0) || \ 647 | (SMTPc_CFG_PW_MAX_LEN > DEF_INT_08U_MAX_VAL)) 648 | #error "SMTPc_CFG_PW_MAX_LEN illegally #define'd in 'smtp-c_cfg.h' [MUST be >= 0 && <= 255]" 649 | #endif 650 | 651 | 652 | 653 | #ifndef SMTPc_CFG_MBOX_NAME_DISP_LEN 654 | #error "SMTPc_CFG_MBOX_NAME_DISP_LEN not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 655 | #elif ((SMTPc_CFG_MBOX_NAME_DISP_LEN < 0) || \ 656 | (SMTPc_CFG_MBOX_NAME_DISP_LEN > DEF_INT_08U_MAX_VAL)) 657 | #error "SMTPc_CFG_MBOX_NAME_DISP_LEN illegally #define'd in 'smtp-c_cfg.h' [MUST be >= 0 && <= 255]" 658 | #endif 659 | 660 | 661 | #ifndef SMTPc_CFG_MSG_SUBJECT_LEN 662 | #error "SMTPc_CFG_MSG_SUBJECT_LEN not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 663 | #elif ((SMTPc_CFG_MSG_SUBJECT_LEN < 0) || \ 664 | (SMTPc_CFG_MSG_SUBJECT_LEN > DEF_INT_08U_MAX_VAL)) 665 | #error "SMTPc_CFG_MSG_SUBJECT_LEN illegally #define'd in 'smtp-c_cfg.h' [MUST be >= 0 && <= 255]" 666 | #endif 667 | 668 | 669 | #ifndef SMTPc_CFG_MSG_MAX_TO 670 | #error "SMTPc_CFG_MSG_MAX_TO not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 671 | #elif ((SMTPc_CFG_MSG_MAX_TO < 0) || \ 672 | (SMTPc_CFG_MSG_MAX_TO > DEF_INT_08U_MAX_VAL)) 673 | #error "SMTPc_CFG_MSG_MAX_TO illegally #define'd in 'smtp-c_cfg.h' [MUST be >= 0 && <= 255]" 674 | #endif 675 | 676 | 677 | #ifndef SMTPc_CFG_MSG_MAX_CC 678 | #error "SMTPc_CFG_MSG_MAX_CC not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 679 | #elif ((SMTPc_CFG_MSG_MAX_CC < 0) || \ 680 | (SMTPc_CFG_MSG_MAX_CC > DEF_INT_08U_MAX_VAL)) 681 | #error "SMTPc_CFG_MSG_MAX_CC illegally #define'd in 'smtp-c_cfg.h' [MUST be >= 0 && <= 255]" 682 | #endif 683 | 684 | 685 | #ifndef SMTPc_CFG_MSG_MAX_BCC 686 | #error "SMTPc_CFG_MSG_MAX_BCC not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 687 | #elif ((SMTPc_CFG_MSG_MAX_BCC < 0) || \ 688 | (SMTPc_CFG_MSG_MAX_BCC > DEF_INT_08U_MAX_VAL)) 689 | #error "SMTPc_CFG_MSG_MAX_BCC illegally #define'd in 'smtp-c_cfg.h' [MUST be >= 0 && <= 255]" 690 | #endif 691 | 692 | 693 | #ifndef SMTPc_CFG_MSG_MAX_ATTACH 694 | #error "SMTPc_CFG_MSG_MAX_ATTACH not #define'd in 'smtp-c_cfg.h' see template file in package named 'smtp-c_cfg.h'" 695 | #elif ((SMTPc_CFG_MSG_MAX_ATTACH < 0) || \ 696 | (SMTPc_CFG_MSG_MAX_ATTACH > DEF_INT_08U_MAX_VAL)) 697 | #error "SMTPc_CFG_MSG_MAX_ATTACH illegally #define'd in 'smtp-c_cfg.h' [MUST be >= 0 && <= 255]" 698 | #endif 699 | 700 | 701 | /* 702 | ********************************************************************************************************* 703 | * MODULE END 704 | ********************************************************************************************************* 705 | */ 706 | 707 | #endif /* End of SMTPc module include. */ 708 | 709 | --------------------------------------------------------------------------------