Parcourir la source

预添加附件发送功能

WKJay il y a 5 ans
Parent
commit
c8f0ca82fc
6 fichiers modifiés avec 232 ajouts et 39 suppressions
  1. 11 16
      example/smtp_client_example.c
  2. 10 0
      inc/smtp_client.h
  3. 21 4
      inc/smtp_client_private.h
  4. 1 4
      readme.md
  5. 186 13
      src/smtp_client.c
  6. 3 2
      src/smtp_client_tls.c

+ 11 - 16
example/smtp_client_example.c

@@ -18,25 +18,24 @@
 
 
 //若使用TLS加密则需要更大的堆栈空间
 //若使用TLS加密则需要更大的堆栈空间
 #ifdef SMTP_CLIENT_USING_TLS
 #ifdef SMTP_CLIENT_USING_TLS
-#define SMTP_CLIENT_THREAD_STACK_SIZE 4096
+#define SMTP_CLIENT_THREAD_STACK_SIZE 8192
 #else
 #else
-#define SMTP_CLIENT_THREAD_STACK_SIZE 2048
+#define SMTP_CLIENT_THREAD_STACK_SIZE 4096
 #endif
 #endif
 
 
 /*
 /*
  *邮件信息相关宏定义
  *邮件信息相关宏定义
  */
  */
 //smtp 服务器域名
 //smtp 服务器域名
-#define SMTP_SERVER_ADDR "smtp.qq.com"
+#define SMTP_SERVER_ADDR "smtp.163.com"
 //smtp 服务器端口号
 //smtp 服务器端口号
 #define SMTP_SERVER_PORT "25"
 #define SMTP_SERVER_PORT "25"
 //smtp 登录用户名
 //smtp 登录用户名
-#define SMTP_USERNAME    ""
+#define SMTP_USERNAME ""
 //smtp 登录密码(或凭证)
 //smtp 登录密码(或凭证)
-#define SMTP_PASSWORD    ""
+#define SMTP_PASSWORD ""
 //邮件主题
 //邮件主题
-#define SMTP_SUBJECT     "SMTP TEST"
-
+#define SMTP_SUBJECT "SMTP TEST"
 
 
 //邮件内容
 //邮件内容
 char *content = "THIS IS SMTP TEST\r\n"
 char *content = "THIS IS SMTP TEST\r\n"
@@ -44,7 +43,7 @@ char *content = "THIS IS SMTP TEST\r\n"
                 "--------------------------------------\r\n"
                 "--------------------------------------\r\n"
                 "based on --->   RT-Thread\r\n"
                 "based on --->   RT-Thread\r\n"
                 "based on ---> SMTP_CLIENT\r\n";
                 "based on ---> SMTP_CLIENT\r\n";
-                
+
 void smtp_thread(void *param)
 void smtp_thread(void *param)
 {
 {
     //手动延时等待网络初始化成功
     //手动延时等待网络初始化成功
@@ -56,16 +55,12 @@ void smtp_thread(void *param)
     smtp_set_server_addr(SMTP_SERVER_ADDR, ADDRESS_TYPE_DOMAIN, SMTP_SERVER_PORT);
     smtp_set_server_addr(SMTP_SERVER_ADDR, ADDRESS_TYPE_DOMAIN, SMTP_SERVER_PORT);
     //设置服务器认证信息
     //设置服务器认证信息
     smtp_set_auth(SMTP_USERNAME, SMTP_PASSWORD);
     smtp_set_auth(SMTP_USERNAME, SMTP_PASSWORD);
-    
+
     //添加收件人1
     //添加收件人1
-    smtp_add_receiver("abc@test.com");
-    //添加收件人2
-    smtp_add_receiver("def@test.com");
-    //添加收件人3
-    smtp_add_receiver("hij@test.com");
-    //删除收件人2
-    smtp_delete_receiver("def@test.com");
+    smtp_add_receiver("roraxef370@royandk.com");
 
 
+    smtp_add_attachment("/a.txt", "a.txt");
+    smtp_add_attachment("/b.txt", "b.txt");
     //发送邮件
     //发送邮件
     rt_kprintf("\r\n[smtp]: O > start to send mail\r\n");
     rt_kprintf("\r\n[smtp]: O > start to send mail\r\n");
     if (smtp_send_mail(SMTP_SUBJECT, content) == 0)
     if (smtp_send_mail(SMTP_SUBJECT, content) == 0)

+ 10 - 0
inc/smtp_client.h

@@ -1,6 +1,7 @@
 #ifndef __SMTP_H
 #ifndef __SMTP_H
 #define __SMTP_H
 #define __SMTP_H
 #include <stdint.h>
 #include <stdint.h>
+#include <rtconfig.h>
 
 
 //域名类型
 //域名类型
 #define ADDRESS_TYPE_DOMAIN 0
 #define ADDRESS_TYPE_DOMAIN 0
@@ -19,4 +20,13 @@ int smtp_send_mail(char *subject, char *body);
 int smtp_add_receiver(char *receiver_addr);
 int smtp_add_receiver(char *receiver_addr);
 //删除指定收件人
 //删除指定收件人
 int smtp_delete_receiver(char *receiver_addr);
 int smtp_delete_receiver(char *receiver_addr);
+//删除所有收件人
+void smtp_clear_receiver(void);
+
+#ifdef SMTP_CLIENT_USING_ATTACHMENT
+//添加附件
+int smtp_add_attachment(char *file_path, char *file_name);
+
+#endif
+
 #endif /* __SMTP_H */
 #endif /* __SMTP_H */

+ 21 - 4
inc/smtp_client_private.h

@@ -17,8 +17,14 @@
 #include <tls_client.h>
 #include <tls_client.h>
 #endif
 #endif
 
 
+#ifdef SMTP_CLIENT_USING_ATTACHMENT
+#include <dfs_posix.h>
+#endif
+
 #define SMTP_MAX_ADDR_LEN 100
 #define SMTP_MAX_ADDR_LEN 100
 #define SMTP_MAX_AUTH_LEN 50
 #define SMTP_MAX_AUTH_LEN 50
+#define SMTP_MAX_FILE_PATH_LEN 64
+#define SMTP_ATTACHMENT_MAX_NAME_LEN 32
 #define SMTP_SEND_CMD_MAX_LEN 100
 #define SMTP_SEND_CMD_MAX_LEN 100
 #define SMTP_SEND_DATA_HEAD_MAX_LENGTH 128
 #define SMTP_SEND_DATA_HEAD_MAX_LENGTH 128
 #define SMTP_SEND_DATA_MAX_LEN 512
 #define SMTP_SEND_DATA_MAX_LEN 512
@@ -52,6 +58,14 @@ typedef struct _smtp_address_to
     struct _smtp_address_to *next;
     struct _smtp_address_to *next;
 } smtp_address_to_t;
 } smtp_address_to_t;
 
 
+//smtp附件链
+typedef struct _smtp_attachments
+{
+    char file_path[SMTP_MAX_FILE_PATH_LEN];
+    char file_name[SMTP_ATTACHMENT_MAX_NAME_LEN];
+    struct _smtp_attachments *next;
+} smtp_attachments_t;
+
 //smtp 会话结构
 //smtp 会话结构
 typedef struct
 typedef struct
 {
 {
@@ -60,11 +74,11 @@ typedef struct
     //会话超时时间,如果时间为0,标志超时,则自动关闭连接
     //会话超时时间,如果时间为0,标志超时,则自动关闭连接
     uint16_t timer;
     uint16_t timer;
     //smtp服务器域名
     //smtp服务器域名
-    const char *server_domain;
+    char *server_domain;
     //smtp服务器ip
     //smtp服务器ip
-    const char *server_ip;
+    char *server_ip;
     //smtp服务器端口号
     //smtp服务器端口号
-    const char *server_port;
+    char *server_port;
     //用户名
     //用户名
     char username[SMTP_MAX_AUTH_LEN * 2];
     char username[SMTP_MAX_AUTH_LEN * 2];
     //密码(有些邮箱服务器需要的是用户凭据)
     //密码(有些邮箱服务器需要的是用户凭据)
@@ -79,6 +93,9 @@ typedef struct
     char *body;
     char *body;
     //smtp连接句柄
     //smtp连接句柄
     int conn_fd;
     int conn_fd;
+#ifdef SMTP_CLIENT_USING_ATTACHMENT
+    smtp_attachments_t *attachments;
+#endif
 #ifdef SMTP_CLIENT_USING_TLS
 #ifdef SMTP_CLIENT_USING_TLS
     //tls会话
     //tls会话
     MbedTLSSession *tls_session;
     MbedTLSSession *tls_session;
@@ -112,7 +129,7 @@ extern smtp_session_t smtp_session;
 
 
 #ifdef SMTP_CLIENT_USING_TLS
 #ifdef SMTP_CLIENT_USING_TLS
 //向SSL/TLS中写入数据
 //向SSL/TLS中写入数据
-int smtp_mbedtls_client_write(MbedTLSSession *tls_session, char *buf);
+int smtp_mbedtls_client_write(MbedTLSSession *tls_session, uint8_t *buf, uint32_t len);
 //从 SSL/TLS 中读取数据
 //从 SSL/TLS 中读取数据
 int smtp_mbedtls_client_read(MbedTLSSession *tls_session, char *buf, size_t len);
 int smtp_mbedtls_client_read(MbedTLSSession *tls_session, char *buf, size_t len);
 
 

+ 1 - 4
readme.md

@@ -1,10 +1,7 @@
 # SMTP_CLIENT 
 # SMTP_CLIENT 
 
 
-#### 最新版 V1.0.1
+#### 当前版本:V1.0.2
 
 
-`该版本属于最新测试版,拥有新增功能,对于新功能有需求的开发者可以选用最新版,最新版不能保证新功能的稳定性,若在使用过程中出现问题请联系该软件包的维护者或在GITHUB中提交ISSUE。谢谢支持`
-
-**本版本部分api在使用时与上一个版本有区别,若使用之前的版本,请参照下方对应使用说明**
 
 
 |版本|连接|
 |版本|连接|
 |---|---|
 |---|---|

+ 186 - 13
src/smtp_client.c

@@ -27,6 +27,82 @@
 
 
 smtp_session_t smtp_session;
 smtp_session_t smtp_session;
 
 
+#ifdef SMTP_CLIENT_USING_ATTACHMENT
+/**
+ * Name:    smtp_add_attachment
+ * Brief:   添加附件
+ * Input:   
+ *  @file_path: 文件路径
+ *  @file_name: 文件名
+ * Output:  成功:0 , 失败:-1
+ */
+int smtp_add_attachment(char *file_path, char *file_name)
+{
+    if (strlen(file_path) > SMTP_MAX_FILE_PATH_LEN)
+    {
+        LOG_E("attachment's file path too large");
+        return -1;
+    }
+
+    if (strlen(file_name) > SMTP_ATTACHMENT_MAX_NAME_LEN)
+    {
+        LOG_E("attachment's file name too large");
+        return -1;
+    }
+
+    if (!smtp_session.attachments)
+    {
+        smtp_session.attachments = rt_malloc(sizeof(smtp_attachments_t));
+        if (smtp_session.attachments)
+        {
+            rt_memset(smtp_session.attachments, 0, sizeof(smtp_attachments_t));
+            rt_memcpy(smtp_session.attachments->file_path, file_path, strlen(file_path));
+            rt_memcpy(smtp_session.attachments->file_name, file_name, strlen(file_name));
+        }
+        else
+        {
+            LOG_E("attachment memory allocate failed");
+            return -1;
+        }
+    }
+    else
+    {
+        smtp_attachments_t *cur_att = smtp_session.attachments;
+        while (cur_att->next)
+        {
+            cur_att = cur_att->next;
+        }
+        cur_att->next = rt_malloc(sizeof(smtp_attachments_t));
+        if (cur_att->next)
+        {
+            rt_memset(cur_att->next, 0, sizeof(smtp_attachments_t));
+            rt_memcpy(cur_att->next->file_path, file_path, strlen(file_path));
+            rt_memcpy(cur_att->next->file_name, file_name, strlen(file_name));
+        }
+        else
+        {
+            LOG_E("attachment memory allocate failed");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+//清除所有附件
+static void smtp_clear_attachments(void)
+{
+    smtp_attachments_t *cur_attr, *next_attr;
+    for (cur_attr = smtp_session.attachments; cur_attr; cur_attr = next_attr)
+    {
+        next_attr = cur_attr->next;
+        LOG_D("delete attachment:%s", cur_attr->file_path);
+        rt_free(cur_attr);
+    }
+    smtp_session.attachments = NULL;
+}
+#endif
+
 /**
 /**
  * Name:    smtp_client_init
  * Name:    smtp_client_init
  * Brief:   初始化smtp客户端
  * Brief:   初始化smtp客户端
@@ -90,7 +166,11 @@ int smtp_set_server_addr(const char *server_addr, uint8_t addr_type, const char
 
 
     if (addr_type == ADDRESS_TYPE_DOMAIN)
     if (addr_type == ADDRESS_TYPE_DOMAIN)
     {
     {
-        smtp_session.server_domain = server_addr;
+        if (smtp_session.server_domain)
+        {
+            rt_free(smtp_session.server_domain);
+        }
+        smtp_session.server_domain = rt_strdup(server_addr);
     }
     }
     else
     else
     {
     {
@@ -101,7 +181,11 @@ int smtp_set_server_addr(const char *server_addr, uint8_t addr_type, const char
         }
         }
         else
         else
         {
         {
-            smtp_session.server_ip = server_addr;
+            if (smtp_session.server_ip)
+            {
+                rt_free(smtp_session.server_ip);
+            }
+            smtp_session.server_ip = rt_strdup(server_addr);
         }
         }
     }
     }
 
 
@@ -112,7 +196,11 @@ int smtp_set_server_addr(const char *server_addr, uint8_t addr_type, const char
     }
     }
     else
     else
     {
     {
-        smtp_session.server_port = port;
+        if (smtp_session.server_port)
+        {
+            rt_free(smtp_session.server_port);
+        }
+        smtp_session.server_port = rt_strdup(port);
     }
     }
     return 0;
     return 0;
 }
 }
@@ -143,6 +231,9 @@ int smtp_set_auth(const char *username, const char *password)
         return -1;
         return -1;
     }
     }
     memset(smtp_session.address_from, 0, SMTP_MAX_ADDR_LEN);
     memset(smtp_session.address_from, 0, SMTP_MAX_ADDR_LEN);
+    memset(smtp_session.username, 0, sizeof(smtp_session.username));
+    memset(smtp_session.password, 0, sizeof(smtp_session.password));
+
     memcpy(smtp_session.address_from, username, username_len);
     memcpy(smtp_session.address_from, username, username_len);
 
 
     if (smtp_base64_encode(smtp_session.username, SMTP_MAX_AUTH_LEN * 2, username, username_len) == 0)
     if (smtp_base64_encode(smtp_session.username, SMTP_MAX_AUTH_LEN * 2, username, username_len) == 0)
@@ -303,29 +394,30 @@ static int smtp_flush(void)
  * Brief:   根据不同的状态调用对应的write
  * Brief:   根据不同的状态调用对应的write
  * Input:
  * Input:
  *  @buf:   要写入的数据
  *  @buf:   要写入的数据
+ *  @len:   写入长度
  * Output:  成功写入的个数,错误返回-1
  * Output:  成功写入的个数,错误返回-1
  */
  */
-static int smtp_write(char *buf)
+static int smtp_write(uint8_t *buf, uint32_t len)
 {
 {
     int server_port_num = atoi(smtp_session.server_port);
     int server_port_num = atoi(smtp_session.server_port);
     if (server_port_num == 25)
     if (server_port_num == 25)
     {
     {
-        return write(smtp_session.conn_fd, buf, strlen(buf));
+        return write(smtp_session.conn_fd, buf, len);
     }
     }
 #ifdef SMTP_CLIENT_USING_TLS
 #ifdef SMTP_CLIENT_USING_TLS
     else if (server_port_num == 465)
     else if (server_port_num == 465)
     {
     {
-        return smtp_mbedtls_client_write(smtp_session.tls_session, buf);
+        return smtp_mbedtls_client_write(smtp_session.tls_session, buf, len);
     }
     }
     else if (server_port_num == 587)
     else if (server_port_num == 587)
     {
     {
         if (smtp_session.state < SMTP_FINISH_START_TLS)
         if (smtp_session.state < SMTP_FINISH_START_TLS)
         {
         {
-            return write(smtp_session.conn_fd, buf, strlen(buf));
+            return write(smtp_session.conn_fd, buf, len);
         }
         }
         else
         else
         {
         {
-            return smtp_mbedtls_client_write(smtp_session.tls_session, buf);
+            return smtp_mbedtls_client_write(smtp_session.tls_session, buf, len);
         }
         }
     }
     }
 #endif
 #endif
@@ -441,7 +533,7 @@ static int smtp_send_data_with_response_check(char *buf, char *response_code)
     else
     else
     {
     {
         smtp_flush();
         smtp_flush();
-        if (smtp_write(buf) != strlen(buf))
+        if (smtp_write((uint8_t *)buf, strlen(buf)) != strlen(buf))
         {
         {
             LOG_E(">smtp send fail");
             LOG_E(">smtp send fail");
             smtp_close_connection();
             smtp_close_connection();
@@ -597,6 +689,46 @@ static int smtp_set_sender_receiver(void)
     return 0;
     return 0;
 }
 }
 
 
+/**
+ * Name:    smtp_send_content
+ * Brief:   smtp发送附件
+ * Input:   None
+ * Output:  None
+ */
+static void smtp_send_attachment(void)
+{
+    uint8_t attachment_buf[SMTP_SEND_DATA_MAX_LEN];
+    smtp_attachments_t *cur_attr = smtp_session.attachments;
+    while (cur_attr)
+    {
+        FILE *fp = fopen(cur_attr->file_path, "r");
+        if (fp)
+        {
+            uint32_t read_size = 0;
+            //发送附件头
+            rt_memset(attachment_buf, 0, sizeof(attachment_buf));
+            sprintf((char *)attachment_buf,
+                    "--mail_boundry\r\nContent-Type: text/plain; name=\"%s\"\r\nContent-Transfer-Encoding: binary\r\nContent-Disposition: attachment; filename=\"%s\"\r\n\r\n",
+                    cur_attr->file_name, cur_attr->file_name);
+            smtp_write(attachment_buf, strlen((char *)attachment_buf));
+
+            //发送附件数据
+            rt_memset(attachment_buf, 0, sizeof(attachment_buf));
+            read_size = fread(attachment_buf, 1, sizeof(attachment_buf), fp);
+            while (read_size == sizeof(attachment_buf))
+            {
+                smtp_write(attachment_buf, read_size);
+                read_size = fread(attachment_buf, 1, sizeof(attachment_buf), fp);
+                rt_thread_mdelay(1);
+            }
+            smtp_write(attachment_buf, read_size);
+            smtp_write("\r\n\r\n", strlen("\r\n\r\n"));
+            fclose(fp);
+        }
+        cur_attr = cur_attr->next;
+    }
+}
+
 /**
 /**
  * Name:    smtp_send_content
  * Name:    smtp_send_content
  * Brief:   smtp发送邮件内容
  * Brief:   smtp发送邮件内容
@@ -615,10 +747,30 @@ static int smtp_send_content(void)
         return -1;
         return -1;
     }
     }
     //拼接内容
     //拼接内容
-    sprintf(content_buf, "FROM: <%s>\r\nTO: <%s>\r\nSUBJECT:%s\r\n\r\n%s\r\n.\r\n",
+
+#ifdef SMTP_CLIENT_USING_ATTACHMENT
+    if (smtp_session.attachments)
+    {
+        sprintf(content_buf, "FROM:<%s>\r\nTO:<%s>\r\nSUBJECT:%s\r\nContent-Type: multipart/mixed; boundary=\"mail_boundry\"\r\n\r\n--mail_boundry\r\nContent-Type: text/plain; charset=\"utf-8\"\r\nContent-Transfer-Encoding: 7bit\r\n\r\n%s\r\n\r\n",
+                smtp_session.address_from, smtp_session.address_to->addr, smtp_session.subject, smtp_session.body);
+    }
+    else
+    {
+        sprintf(content_buf, "FROM: <%s>\r\nTO: <%s>\r\nSUBJECT:%s\r\n\r\n%s\r\n\r\n",
+                smtp_session.address_from, smtp_session.address_to->addr, smtp_session.subject, smtp_session.body);
+    }
+
+#else
+    sprintf(content_buf, "FROM: <%s>\r\nTO: <%s>\r\nSUBJECT:%s\r\n\r\n%s\r\n\r\n",
             smtp_session.address_from, smtp_session.address_to->addr, smtp_session.subject, smtp_session.body);
             smtp_session.address_from, smtp_session.address_to->addr, smtp_session.subject, smtp_session.body);
+#endif
+    smtp_write((uint8_t *)content_buf, strlen(content_buf));
 
 
-    if (smtp_send_data_with_response_check(content_buf, "250") != 0)
+#ifdef SMTP_CLIENT_USING_ATTACHMENT
+    smtp_send_attachment();
+    smtp_clear_attachments();
+#endif
+    if (smtp_send_data_with_response_check(SMTP_CMD_BODY_FINISHED, "250") != 0)
     {
     {
         LOG_E(">smtp send data content fail");
         LOG_E(">smtp send data content fail");
         smtp_close_connection();
         smtp_close_connection();
@@ -786,7 +938,7 @@ int smtp_add_receiver(char *receiver_addr)
         LOG_W("start to free address node");
         LOG_W("start to free address node");
         //找出需要释放节点的上一个节点,并将其next指向空
         //找出需要释放节点的上一个节点,并将其next指向空
         smtp_address_to_free_temp = smtp_session.address_to;
         smtp_address_to_free_temp = smtp_session.address_to;
-        while(smtp_address_to_free_temp->next != smtp_address_to_temp)
+        while (smtp_address_to_free_temp->next != smtp_address_to_temp)
         {
         {
             smtp_address_to_free_temp = smtp_address_to_free_temp->next;
             smtp_address_to_free_temp = smtp_address_to_free_temp->next;
         }
         }
@@ -794,7 +946,7 @@ int smtp_add_receiver(char *receiver_addr)
         //释放问题节点
         //释放问题节点
         rt_free(smtp_address_to_temp);
         rt_free(smtp_address_to_temp);
         LOG_I("address node free success!");
         LOG_I("address node free success!");
-        
+
         return -1;
         return -1;
     }
     }
     memset(smtp_address_to_temp->addr, 0, strlen(receiver_addr) + 1);
     memset(smtp_address_to_temp->addr, 0, strlen(receiver_addr) + 1);
@@ -802,6 +954,27 @@ int smtp_add_receiver(char *receiver_addr)
     return 0;
     return 0;
 }
 }
 
 
+/**
+ * Name:    smtp_clear_receiver
+ * Brief:   删除所有收件人
+ * Input:   None
+ * Output:  None
+ */
+void smtp_clear_receiver(void)
+{
+    //上一个节点指针
+    smtp_address_to_t *cur_receiver, *next_receiver;
+
+    for (cur_receiver = smtp_session.address_to; cur_receiver; cur_receiver = next_receiver)
+    {
+        next_receiver = cur_receiver->next;
+        LOG_D("delete receiver:%s", cur_receiver->addr);
+        rt_free(cur_receiver->addr);
+        rt_free(cur_receiver);
+    }
+    smtp_session.address_to = NULL;
+}
+
 /**
 /**
  * Name:    smtp_delete_receiver
  * Name:    smtp_delete_receiver
  * Brief:   删除某个收件人
  * Brief:   删除某个收件人

+ 3 - 2
src/smtp_client_tls.c

@@ -162,12 +162,13 @@ static int smtp_mbedtls_client_connect(MbedTLSSession *tls_session)
  * Input:
  * Input:
  *  @smtp_session:  smtp会话
  *  @smtp_session:  smtp会话
  *  @buf:           写入的字符串
  *  @buf:           写入的字符串
+ *  @len:           写入长度
  * Output:  成功写入的字符个数,失败返回-1或0并关闭tls连接
  * Output:  成功写入的字符个数,失败返回-1或0并关闭tls连接
  */
  */
-int smtp_mbedtls_client_write(MbedTLSSession *tls_session, char *buf)
+int smtp_mbedtls_client_write(MbedTLSSession *tls_session, uint8_t *buf, uint32_t len)
 {
 {
     int result = -1;
     int result = -1;
-    while ((result = mbedtls_client_write(tls_session, (const unsigned char *)buf, strlen(buf))) <= 0)
+    while ((result = mbedtls_client_write(tls_session, (const unsigned char *)buf, len)) <= 0)
     {
     {
         if (result != MBEDTLS_ERR_SSL_WANT_READ && result != MBEDTLS_ERR_SSL_WANT_WRITE)
         if (result != MBEDTLS_ERR_SSL_WANT_READ && result != MBEDTLS_ERR_SSL_WANT_WRITE)
         {
         {