list.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package list
  2. import (
  3. "fmt"
  4. "github.com/Jinnrry/pmail/db"
  5. "github.com/Jinnrry/pmail/dto"
  6. "github.com/Jinnrry/pmail/dto/response"
  7. "github.com/Jinnrry/pmail/models"
  8. "github.com/Jinnrry/pmail/utils/array"
  9. "github.com/Jinnrry/pmail/utils/context"
  10. log "github.com/sirupsen/logrus"
  11. "strings"
  12. )
  13. import . "xorm.io/builder"
  14. func GetEmailList(ctx *context.Context, tagInfo dto.SearchTag, keyword string, pop3List bool, offset, limit int) (emailList []*response.EmailResponseData, total int64) {
  15. return getList(ctx, tagInfo, keyword, pop3List, offset, limit)
  16. }
  17. func getList(ctx *context.Context, tagInfo dto.SearchTag, keyword string, pop3List bool, offset, limit int) (emailList []*response.EmailResponseData, total int64) {
  18. querySQL, queryParams := genSQL(ctx, false, tagInfo, keyword, pop3List, offset, limit)
  19. err := db.Instance.SQL(querySQL, queryParams...).Find(&emailList)
  20. if err != nil {
  21. log.WithContext(ctx).Errorf("SQL ERROR: %s ,Error:%s", querySQL, err)
  22. }
  23. totalSQL, totalParams := genSQL(ctx, true, tagInfo, keyword, pop3List, offset, limit)
  24. _, err = db.Instance.SQL(totalSQL, totalParams...).Get(&total)
  25. if err != nil {
  26. log.WithContext(ctx).Errorf("SQL ERROR: %s ,Error:%s", querySQL, err)
  27. }
  28. return emailList, total
  29. }
  30. func genSQL(ctx *context.Context, count bool, tagInfo dto.SearchTag, keyword string, pop3List bool, offset, limit int) (string, []any) {
  31. sqlParams := []any{ctx.UserID}
  32. sql := "select "
  33. if count {
  34. sql += `count(1) from email e left join user_email ue on e.id=ue.email_id where ue.user_id = ? `
  35. } else if pop3List {
  36. sql += `e.id,e.size from email e left join user_email ue on e.id=ue.email_id where ue.user_id = ? `
  37. } else {
  38. sql += `e.*,ue.is_read from email e left join user_email ue on e.id=ue.email_id where ue.user_id = ? `
  39. }
  40. if tagInfo.Status != -1 {
  41. sql += " and ue.status =? "
  42. sqlParams = append(sqlParams, tagInfo.Status)
  43. } else if tagInfo.Status == -1 {
  44. if tagInfo.Type != 1 {
  45. sql += " and ue.status = 0"
  46. }
  47. }
  48. if tagInfo.Type != -1 {
  49. sql += " and type =? "
  50. sqlParams = append(sqlParams, tagInfo.Type)
  51. }
  52. if tagInfo.GroupId != -1 {
  53. sql += " and ue.group_id=? "
  54. sqlParams = append(sqlParams, tagInfo.GroupId)
  55. } else {
  56. sql += " and ue.group_id=0 "
  57. }
  58. if keyword != "" {
  59. sql += " and (subject like ? or text like ? )"
  60. sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%")
  61. }
  62. if limit == 0 {
  63. limit = 10
  64. }
  65. sql += " order by e.id desc"
  66. if limit < 10000 {
  67. sql += fmt.Sprintf(" LIMIT %d OFFSET %d ", limit, offset)
  68. }
  69. return sql, sqlParams
  70. }
  71. type statRes struct {
  72. Total int64
  73. Size int64
  74. }
  75. // Stat 查询邮件总数和大小
  76. func Stat(ctx *context.Context) (int64, int64) {
  77. sql := `select count(1) as total,sum(size) as size from email e left join user_email ue on e.id=ue.email_id where ue.user_id = ? and e.type = 0 and ue.status != 3`
  78. var ret statRes
  79. _, err := db.Instance.SQL(sql, ctx.UserID).Get(&ret)
  80. if err != nil {
  81. log.WithContext(ctx).Errorf("SQL ERROR: %s ,Error:%s", sql, err)
  82. }
  83. return ret.Total, ret.Size
  84. }
  85. type ImapListReq struct {
  86. UidList []int
  87. Star int
  88. End int
  89. }
  90. func GetUEListByUID(ctx *context.Context, groupName string, star, end int, uidList []int) []*response.UserEmailUIDData {
  91. var ue []*response.UserEmailUIDData
  92. sql := "SELECT id,email_id, is_read, ROW_NUMBER() OVER (ORDER BY id) AS serial_number FROM `user_email` WHERE user_id = ? "
  93. params := []any{ctx.UserID}
  94. if len(uidList) > 0 {
  95. sql += fmt.Sprintf(" and id in (%s)", array.Join(uidList, ","))
  96. }
  97. if star > 0 {
  98. sql += " and id >=?"
  99. params = append(params, star)
  100. }
  101. if end > 0 {
  102. sql += " and id <=?"
  103. params = append(params, end)
  104. }
  105. switch groupName {
  106. case "INBOX":
  107. sql += " and status =?"
  108. params = append(params, 0)
  109. case "Sent Messages":
  110. sql += " and status =?"
  111. params = append(params, 1)
  112. case "Drafts":
  113. sql += " and status =?"
  114. params = append(params, 4)
  115. case "Deleted Messages":
  116. sql += " and status =?"
  117. params = append(params, 3)
  118. case "Junk":
  119. sql += " and status =?"
  120. params = append(params, 5)
  121. default:
  122. groupNames := strings.Split(groupName, "/")
  123. groupName = groupNames[len(groupNames)-1]
  124. var group models.Group
  125. db.Instance.Table("group").Where("user_id=? and name=?", ctx.UserID, groupName).Get(&group)
  126. if group.ID == 0 {
  127. return nil
  128. }
  129. sql += " and group_id = ?"
  130. params = append(params, group.ID)
  131. }
  132. db.Instance.SQL(sql, params...).Find(&ue)
  133. return ue
  134. }
  135. func getEmailListByUidList(ctx *context.Context, groupName string, req ImapListReq, uid bool) []*response.EmailResponseData {
  136. var ret []*response.EmailResponseData
  137. var ue []*response.UserEmailUIDData
  138. sql := fmt.Sprintf("SELECT id,email_id, is_read, ROW_NUMBER() OVER (ORDER BY id) AS serial_number FROM `user_email` WHERE (user_id = ? and id in (%s))", array.Join(req.UidList, ","))
  139. if req.Star > 0 && req.End != 0 {
  140. sql = fmt.Sprintf("SELECT id,email_id, is_read, ROW_NUMBER() OVER (ORDER BY id) AS serial_number FROM `user_email` WHERE (user_id = ? and id >=%d and id <= %d)", req.Star, req.End)
  141. }
  142. if req.Star > 0 && req.End == 0 {
  143. sql = fmt.Sprintf("SELECT id,email_id, is_read, ROW_NUMBER() OVER (ORDER BY id) AS serial_number FROM `user_email` WHERE (user_id = ? and id >=%d )", req.Star)
  144. }
  145. err := db.Instance.SQL(sql, ctx.UserID).Find(&ue)
  146. if err != nil {
  147. log.WithContext(ctx).Errorf("SQL ERROR: %s ,Error:%s", sql, err)
  148. }
  149. ueMap := map[int]*response.UserEmailUIDData{}
  150. var emailIds []int
  151. for _, email := range ue {
  152. ueMap[email.EmailID] = email
  153. emailIds = append(emailIds, email.EmailID)
  154. }
  155. _ = db.Instance.Table("email").Select("*").Where(Eq{"id": emailIds}).Find(&ret)
  156. for i, data := range ret {
  157. ret[i].IsRead = ueMap[data.Id].IsRead
  158. ret[i].SerialNumber = ueMap[data.Id].SerialNumber
  159. ret[i].UeId = ueMap[data.Id].ID
  160. }
  161. return ret
  162. }
  163. func GetEmailListByGroup(ctx *context.Context, groupName string, req ImapListReq, uid bool) []*response.EmailResponseData {
  164. if len(req.UidList) == 0 && req.Star == 0 && req.End == 0 {
  165. return nil
  166. }
  167. if uid {
  168. return getEmailListByUidList(ctx, groupName, req, uid)
  169. }
  170. var ret []*response.EmailResponseData
  171. var ue []*response.UserEmailUIDData
  172. sql := fmt.Sprintf("SELECT * from (SELECT id,email_id, is_read, ROW_NUMBER() OVER (ORDER BY id) AS serial_number FROM `user_email` WHERE (user_id = ? and status = ? and group_id=0 )) a WHERE serial_number in (%s)", array.Join(req.UidList, ","))
  173. if req.Star > 0 && req.End == 0 {
  174. sql = fmt.Sprintf("SELECT * from (SELECT id,email_id, is_read, ROW_NUMBER() OVER (ORDER BY id) AS serial_number FROM `user_email` WHERE (user_id = ? and status = ? and group_id=0 )) a WHERE serial_number >= %d", req.Star)
  175. }
  176. if req.Star > 0 && req.End > 0 {
  177. sql = fmt.Sprintf("SELECT * from (SELECT id,email_id, is_read, ROW_NUMBER() OVER (ORDER BY id) AS serial_number FROM `user_email` WHERE (user_id = ? and status = ? and group_id=0 )) a WHERE serial_number >= %d and serial_number <=%d", req.Star, req.End)
  178. }
  179. switch groupName {
  180. case "INBOX":
  181. db.Instance.SQL(sql, ctx.UserID, 0).Find(&ue)
  182. case "Sent Messages":
  183. db.Instance.SQL(sql, ctx.UserID, 1).Find(&ue)
  184. case "Drafts":
  185. db.Instance.SQL(sql, ctx.UserID, 4).Find(&ue)
  186. case "Deleted Messages":
  187. db.Instance.SQL(sql, ctx.UserID, 3).Find(&ue)
  188. case "Junk":
  189. db.Instance.SQL(sql, ctx.UserID, 5).Find(&ue)
  190. default:
  191. groupNames := strings.Split(groupName, "/")
  192. groupName = groupNames[len(groupNames)-1]
  193. var group models.Group
  194. db.Instance.Table("group").Where("user_id=? and name=?", ctx.UserID, groupName).Get(&group)
  195. if group.ID == 0 {
  196. return ret
  197. }
  198. db.Instance.
  199. SQL(fmt.Sprintf(
  200. "SELECT * from (SELECT id,email_id, is_read, ROW_NUMBER() OVER (ORDER BY id) AS serial_number FROM `user_email` WHERE (user_id = ? and group_id = ?)) a WHERE serial_number in (%s)",
  201. array.Join(req.UidList, ","))).
  202. Find(&ue, ctx.UserID, group.ID)
  203. }
  204. ueMap := map[int]*response.UserEmailUIDData{}
  205. var emailIds []int
  206. for _, email := range ue {
  207. ueMap[email.EmailID] = email
  208. emailIds = append(emailIds, email.EmailID)
  209. }
  210. _ = db.Instance.Table("email").Select("*").Where(Eq{"id": emailIds}).Find(&ret)
  211. for i, data := range ret {
  212. ret[i].IsRead = ueMap[data.Id].IsRead
  213. ret[i].SerialNumber = ueMap[data.Id].SerialNumber
  214. ret[i].UeId = ueMap[data.Id].ID
  215. }
  216. return ret
  217. }