imap.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. package goimap
  2. import (
  3. "bufio"
  4. "crypto/tls"
  5. "encoding/base64"
  6. "errors"
  7. "fmt"
  8. log "github.com/sirupsen/logrus"
  9. "io"
  10. "log/slog"
  11. "net"
  12. "strings"
  13. "sync"
  14. "time"
  15. )
  16. var (
  17. eol = "\r\n"
  18. )
  19. // Server Imap服务实例
  20. type Server struct {
  21. Domain string // 域名
  22. Port int // 端口
  23. TlsEnabled bool //是否启用Tls
  24. TlsConfig *tls.Config // tls配置
  25. ConnectAliveTime time.Duration // 连接存活时间,默认不超时
  26. Action Action
  27. stop chan bool
  28. close bool
  29. lck sync.Mutex
  30. }
  31. // NewImapServer 新建一个服务实例
  32. func NewImapServer(port int, domain string, tlsEnabled bool, tlsConfig *tls.Config, action Action) *Server {
  33. return &Server{
  34. Domain: domain,
  35. Port: port,
  36. TlsEnabled: tlsEnabled,
  37. TlsConfig: tlsConfig,
  38. Action: action,
  39. stop: make(chan bool, 1),
  40. }
  41. }
  42. // Start 启动服务
  43. func (s *Server) Start() error {
  44. if !s.TlsEnabled {
  45. return s.startWithoutTLS()
  46. } else {
  47. return s.startWithTLS()
  48. }
  49. }
  50. func (s *Server) startWithTLS() error {
  51. if s.lck.TryLock() {
  52. listener, err := tls.Listen("tcp", fmt.Sprintf(":%d", s.Port), s.TlsConfig)
  53. if err != nil {
  54. return err
  55. }
  56. s.close = false
  57. defer func() {
  58. listener.Close()
  59. }()
  60. go func() {
  61. for {
  62. conn, err := listener.Accept()
  63. if err != nil {
  64. if s.close {
  65. break
  66. } else {
  67. continue
  68. }
  69. }
  70. go s.handleClient(conn)
  71. }
  72. }()
  73. <-s.stop
  74. } else {
  75. return errors.New("Server Is Running")
  76. }
  77. return nil
  78. }
  79. func (s *Server) startWithoutTLS() error {
  80. if s.lck.TryLock() {
  81. listener, err := net.Listen("tcp", fmt.Sprintf(":%d", s.Port))
  82. if err != nil {
  83. return err
  84. }
  85. s.close = false
  86. defer func() {
  87. listener.Close()
  88. }()
  89. go func() {
  90. for {
  91. conn, err := listener.Accept()
  92. if err != nil {
  93. if s.close {
  94. break
  95. } else {
  96. continue
  97. }
  98. }
  99. go s.handleClient(conn)
  100. }
  101. }()
  102. <-s.stop
  103. } else {
  104. return errors.New("Server Is Running")
  105. }
  106. return nil
  107. }
  108. // Stop 停止服务
  109. func (s *Server) Stop() {
  110. s.close = true
  111. s.stop <- true
  112. }
  113. func (s *Server) authenticate(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  114. if args == "LOGIN" {
  115. write(conn, "+ VXNlciBOYW1lAA=="+eol, "")
  116. line, err2 := reader.ReadString('\n')
  117. if err2 != nil {
  118. if conn != nil {
  119. _ = conn.Close()
  120. }
  121. session.Conn = nil
  122. session.IN_IDLE = false
  123. return
  124. }
  125. account, err := base64.StdEncoding.DecodeString(line)
  126. if err != nil {
  127. showBad(conn, "Data Error.", nub)
  128. return
  129. }
  130. write(conn, "+ UGFzc3dvcmQA"+eol, "")
  131. line, err = reader.ReadString('\n')
  132. if err2 != nil {
  133. if conn != nil {
  134. _ = conn.Close()
  135. }
  136. session.Conn = nil
  137. session.IN_IDLE = false
  138. return
  139. }
  140. password, err := base64.StdEncoding.DecodeString(line)
  141. res := s.Action.Login(session, string(account), string(password))
  142. if res.Type == SUCCESS {
  143. showSucc(conn, res.Message, nub)
  144. } else if res.Type == BAD {
  145. showBad(conn, res.Message, nub)
  146. } else {
  147. showNo(conn, res.Message, nub)
  148. }
  149. } else {
  150. showBad(conn, "Unsupported AUTHENTICATE mechanism.", nub)
  151. }
  152. }
  153. func (s *Server) capability(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  154. res := s.Action.CapaBility(session)
  155. if res.Type == BAD {
  156. write(conn, fmt.Sprintf("* BAD %s%s", res.Message, eol), nub)
  157. } else {
  158. ret := "*"
  159. for _, command := range res.Data {
  160. ret += " " + command
  161. }
  162. ret += eol
  163. write(conn, ret, nub)
  164. showSucc(conn, res.Message, nub)
  165. }
  166. }
  167. func (s *Server) create(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  168. if session.Status != AUTHORIZED {
  169. showBad(conn, "Need Login", nub)
  170. return
  171. }
  172. if args == "" {
  173. paramsErr(conn, "CREATE", nub)
  174. return
  175. }
  176. res := s.Action.Create(session, args)
  177. showSucc(conn, res.Message, nub)
  178. }
  179. func (s *Server) delete(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  180. if session.Status != AUTHORIZED {
  181. showBad(conn, "Need Login", nub)
  182. return
  183. }
  184. if args == "" {
  185. paramsErr(conn, "DELETE", nub)
  186. return
  187. }
  188. res := s.Action.Delete(session, args)
  189. if res.Type == SUCCESS {
  190. showSucc(conn, res.Message, nub)
  191. } else if res.Type == BAD {
  192. showBad(conn, res.Message, nub)
  193. } else {
  194. showNo(conn, res.Message, nub)
  195. }
  196. }
  197. func (s *Server) rename(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  198. if session.Status != AUTHORIZED {
  199. showBad(conn, "Need Login", nub)
  200. return
  201. }
  202. if args == "" {
  203. paramsErr(conn, "RENAME", nub)
  204. } else {
  205. dt := strings.Split(args, " ")
  206. res := s.Action.Rename(session, dt[0], dt[1])
  207. if res.Type == SUCCESS {
  208. showSucc(conn, res.Message, nub)
  209. } else if res.Type == BAD {
  210. showBad(conn, res.Message, nub)
  211. } else {
  212. showNo(conn, res.Message, nub)
  213. }
  214. }
  215. }
  216. func (s *Server) list(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  217. if session.Status != AUTHORIZED {
  218. showBad(conn, "Need Login", nub)
  219. return
  220. }
  221. if args == "" {
  222. paramsErr(conn, "LIST", nub)
  223. } else {
  224. dt := strings.Split(args, " ")
  225. dt[0] = strings.Trim(dt[0], `"`)
  226. dt[1] = strings.Trim(dt[1], `"`)
  227. res := s.Action.List(session, dt[0], dt[1])
  228. if res.Type == SUCCESS {
  229. showSuccWithData(conn, res.Data, res.Message, nub)
  230. } else if res.Type == BAD {
  231. showBad(conn, res.Message, nub)
  232. } else {
  233. showNo(conn, res.Message, nub)
  234. }
  235. }
  236. }
  237. func (s *Server) append(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  238. if session.Status != AUTHORIZED {
  239. showBad(conn, "Need Login", nub)
  240. return
  241. }
  242. log.Debugf("Append: %+v", args)
  243. }
  244. func (s *Server) cselect(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  245. if session.Status != AUTHORIZED {
  246. showBad(conn, "Need Login", nub)
  247. return
  248. }
  249. res := s.Action.Select(session, args)
  250. if res.Type == SUCCESS {
  251. showSuccWithData(conn, res.Data, res.Message, nub)
  252. } else if res.Type == BAD {
  253. showBad(conn, res.Message, nub)
  254. } else {
  255. showNo(conn, res.Message, nub)
  256. }
  257. }
  258. func (s *Server) fetch(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader, uid bool) {
  259. if session.Status != AUTHORIZED {
  260. showBad(conn, "Need Login", nub)
  261. return
  262. }
  263. if args == "" {
  264. paramsErr(conn, "FETCH", nub)
  265. } else {
  266. dt := strings.SplitN(args, " ", 2)
  267. res := s.Action.Fetch(session, dt[0], dt[1], uid)
  268. if res.Type == SUCCESS {
  269. showSuccWithData(conn, res.Data, res.Message, nub)
  270. } else if res.Type == BAD {
  271. showBad(conn, res.Message, nub)
  272. } else {
  273. showNo(conn, res.Message, nub)
  274. }
  275. }
  276. }
  277. func (s *Server) store(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  278. if session.Status != AUTHORIZED {
  279. showBad(conn, "Need Login", nub)
  280. return
  281. }
  282. if args == "" {
  283. paramsErr(conn, "RENAME", nub)
  284. } else {
  285. dt := strings.Split(args, " ")
  286. res := s.Action.Store(session, dt[0], dt[1])
  287. if res.Type == SUCCESS {
  288. showSucc(conn, res.Message, nub)
  289. } else if res.Type == BAD {
  290. showBad(conn, res.Message, nub)
  291. } else {
  292. showNo(conn, res.Message, nub)
  293. }
  294. }
  295. }
  296. func (s *Server) cclose(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  297. res := s.Action.Close(session)
  298. if res.Type == SUCCESS {
  299. showSucc(conn, res.Message, nub)
  300. } else if res.Type == BAD {
  301. showBad(conn, res.Message, nub)
  302. } else {
  303. showNo(conn, res.Message, nub)
  304. }
  305. }
  306. func (s *Server) expunge(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  307. if session.Status != AUTHORIZED {
  308. showBad(conn, "Need Login", nub)
  309. return
  310. }
  311. res := s.Action.Expunge(session)
  312. if res.Type == SUCCESS {
  313. showSucc(conn, res.Message, nub)
  314. } else if res.Type == BAD {
  315. showBad(conn, res.Message, nub)
  316. } else {
  317. showNo(conn, res.Message, nub)
  318. }
  319. }
  320. func (s *Server) examine(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  321. if session.Status != AUTHORIZED {
  322. showBad(conn, "Need Login", nub)
  323. return
  324. }
  325. if args == "" {
  326. paramsErr(conn, "EXAMINE", nub)
  327. }
  328. res := s.Action.Examine(session, args)
  329. if res.Type == SUCCESS {
  330. showSucc(conn, res.Message, nub)
  331. } else if res.Type == BAD {
  332. showBad(conn, res.Message, nub)
  333. } else {
  334. showNo(conn, res.Message, nub)
  335. }
  336. }
  337. func (s *Server) unsubscribe(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  338. if session.Status != AUTHORIZED {
  339. showBad(conn, "Need Login", nub)
  340. return
  341. }
  342. if args == "" {
  343. paramsErr(conn, "UNSUBSCRIBE", nub)
  344. } else {
  345. res := s.Action.UnSubscribe(session, args)
  346. if res.Type == SUCCESS {
  347. showSucc(conn, res.Message, nub)
  348. } else if res.Type == BAD {
  349. showBad(conn, res.Message, nub)
  350. } else {
  351. showNo(conn, res.Message, nub)
  352. }
  353. }
  354. }
  355. func (s *Server) lsub(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  356. if session.Status != AUTHORIZED {
  357. showBad(conn, "Need Login", nub)
  358. return
  359. }
  360. if args == "" {
  361. paramsErr(conn, "LSUB", nub)
  362. } else {
  363. dt := strings.Split(args, " ")
  364. res := s.Action.LSub(session, dt[0], dt[1])
  365. if res.Type == SUCCESS {
  366. showSucc(conn, res.Message, nub)
  367. } else if res.Type == BAD {
  368. showBad(conn, res.Message, nub)
  369. } else {
  370. showNo(conn, res.Message, nub)
  371. }
  372. }
  373. }
  374. func (s *Server) status(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  375. if session.Status != AUTHORIZED {
  376. showBad(conn, "Need Login", nub)
  377. return
  378. }
  379. if args == "" {
  380. paramsErr(conn, "STATUS", nub)
  381. } else {
  382. var mailBox string
  383. var params []string
  384. if strings.HasPrefix(args, `"`) {
  385. dt := strings.Split(args, `"`)
  386. if len(dt) >= 3 {
  387. mailBox = dt[1]
  388. }
  389. dt[2] = strings.Trim(dt[2], "() ")
  390. params = strings.Split(dt[2], " ")
  391. } else {
  392. dt := strings.SplitN(args, " ", 2)
  393. dt[0] = strings.ReplaceAll(dt[0], `"`, "")
  394. dt[1] = strings.Trim(dt[1], "()")
  395. mailBox = dt[0]
  396. params = strings.Split(dt[1], " ")
  397. }
  398. res := s.Action.Status(session, mailBox, params)
  399. if res.Type == SUCCESS {
  400. showSuccWithData(conn, res.Data, res.Message, nub)
  401. } else if res.Type == BAD {
  402. showBad(conn, res.Message, nub)
  403. } else {
  404. showNo(conn, res.Message, nub)
  405. }
  406. }
  407. }
  408. func (s *Server) check(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  409. if session.Status != AUTHORIZED {
  410. showBad(conn, "Need Login", nub)
  411. return
  412. }
  413. res := s.Action.Check(session)
  414. if res.Type == SUCCESS {
  415. showSucc(conn, res.Message, nub)
  416. } else if res.Type == BAD {
  417. showBad(conn, res.Message, nub)
  418. } else {
  419. showNo(conn, res.Message, nub)
  420. }
  421. }
  422. func (s *Server) search(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  423. if session.Status != AUTHORIZED {
  424. showBad(conn, "Need Login", nub)
  425. return
  426. }
  427. if args == "" {
  428. paramsErr(conn, "SEARCH", nub)
  429. } else {
  430. dt := strings.SplitN(args, " ", 2)
  431. res := s.Action.Search(session, dt[0], dt[1])
  432. if res.Type == SUCCESS {
  433. showSucc(conn, res.Message, nub)
  434. } else if res.Type == BAD {
  435. showBad(conn, res.Message, nub)
  436. } else {
  437. showNo(conn, res.Message, nub)
  438. }
  439. }
  440. }
  441. func (s *Server) copy(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  442. if session.Status != AUTHORIZED {
  443. showBad(conn, "Need Login", nub)
  444. return
  445. }
  446. if args == "" {
  447. paramsErr(conn, "COPY", nub)
  448. } else {
  449. dt := strings.SplitN(args, " ", 2)
  450. res := s.Action.Copy(session, dt[0], dt[1])
  451. if res.Type == SUCCESS {
  452. showSucc(conn, res.Message, nub)
  453. } else if res.Type == BAD {
  454. showBad(conn, res.Message, nub)
  455. } else {
  456. showNo(conn, res.Message, nub)
  457. }
  458. }
  459. }
  460. func (s *Server) noop(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  461. res := s.Action.Noop(session)
  462. if res.Type == SUCCESS {
  463. showSucc(conn, res.Message, nub)
  464. } else if res.Type == BAD {
  465. showBad(conn, res.Message, nub)
  466. } else {
  467. showNo(conn, res.Message, nub)
  468. }
  469. }
  470. func (s *Server) login(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  471. if args == "" {
  472. paramsErr(conn, "LOGIN", nub)
  473. } else {
  474. dt := strings.SplitN(args, " ", 2)
  475. res := s.Action.Login(session, strings.Trim(dt[0], `"`), strings.Trim(dt[1], `"`))
  476. if res.Type == SUCCESS {
  477. showSucc(conn, res.Message, nub)
  478. } else if res.Type == BAD {
  479. showBad(conn, res.Message, nub)
  480. } else {
  481. showNo(conn, res.Message, nub)
  482. }
  483. }
  484. }
  485. func (s *Server) logout(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  486. res := s.Action.Logout(session)
  487. write(conn, "* BYE PMail Server logging out"+eol, nub)
  488. if res.Type == SUCCESS {
  489. showSucc(conn, res.Message, nub)
  490. } else if res.Type == BAD {
  491. showBad(conn, res.Message, nub)
  492. } else {
  493. showNo(conn, res.Message, nub)
  494. }
  495. if conn != nil {
  496. _ = conn.Close()
  497. }
  498. }
  499. func (s *Server) unselect(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  500. if session.Status != AUTHORIZED {
  501. showBad(conn, "Need Login", nub)
  502. return
  503. }
  504. res := s.Action.Unselect(session)
  505. if res.Type == SUCCESS {
  506. showSucc(conn, res.Message, nub)
  507. } else if res.Type == BAD {
  508. showBad(conn, res.Message, nub)
  509. } else {
  510. showNo(conn, res.Message, nub)
  511. }
  512. }
  513. func (s *Server) subscribe(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  514. if session.Status != AUTHORIZED {
  515. showBad(conn, "Need Login", nub)
  516. return
  517. }
  518. if args == "" {
  519. paramsErr(conn, "SUBSCRIBE", nub)
  520. } else {
  521. res := s.Action.Subscribe(session, args)
  522. if res.Type == SUCCESS {
  523. showSucc(conn, res.Message, nub)
  524. } else if res.Type == BAD {
  525. showBad(conn, res.Message, nub)
  526. } else {
  527. showNo(conn, res.Message, nub)
  528. }
  529. }
  530. }
  531. func (s *Server) idle(session *Session, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  532. if session.Status != AUTHORIZED {
  533. showBad(conn, "Need Login", nub)
  534. return
  535. }
  536. session.IN_IDLE = true
  537. res := s.Action.IDLE(session)
  538. if res.Type == SUCCESS {
  539. write(conn, "+ idling"+eol, nub)
  540. } else if res.Type == BAD {
  541. showBad(conn, res.Message, nub)
  542. } else {
  543. showNo(conn, res.Message, nub)
  544. }
  545. }
  546. func (s *Server) custom(session *Session, cmd string, args string, nub string, conn net.Conn, reader *bufio.Reader) {
  547. res := s.Action.Custom(session, cmd, args)
  548. if res.Type == BAD {
  549. write(conn, fmt.Sprintf("* BAD %s %s", res.Message, eol), nub)
  550. } else if res.Type == NO {
  551. showNo(conn, res.Message, nub)
  552. } else {
  553. if len(res.Data) == 0 {
  554. showSucc(conn, res.Message, nub)
  555. } else {
  556. ret := ""
  557. for _, re := range res.Data {
  558. ret += fmt.Sprintf("%s%s", re, eol)
  559. }
  560. ret += "." + eol
  561. write(conn, fmt.Sprintf(ret), nub)
  562. }
  563. }
  564. }
  565. func (s *Server) doCommand(session *Session, rawLine string, conn net.Conn, reader *bufio.Reader) {
  566. nub, cmd, args := getCommand(rawLine)
  567. log.Debugf("Imap Input:\t %s", rawLine)
  568. if cmd != "IDLE" {
  569. session.IN_IDLE = false
  570. }
  571. switch cmd {
  572. case "":
  573. if conn != nil {
  574. conn.Close()
  575. conn = nil
  576. }
  577. break
  578. case "AUTHENTICATE":
  579. s.authenticate(session, args, nub, conn, reader)
  580. case "CAPABILITY":
  581. s.capability(session, rawLine, nub, conn, reader)
  582. case "CREATE":
  583. s.create(session, args, nub, conn, reader)
  584. case "DELETE":
  585. s.delete(session, args, nub, conn, reader)
  586. case "RENAME":
  587. s.rename(session, args, nub, conn, reader)
  588. case "LIST":
  589. s.list(session, args, nub, conn, reader)
  590. case "APPEND":
  591. s.append(session, args, nub, conn, reader)
  592. case "SELECT":
  593. s.cselect(session, args, nub, conn, reader)
  594. case "FETCH":
  595. s.fetch(session, args, nub, conn, reader, false)
  596. case "UID FETCH":
  597. s.fetch(session, args, nub, conn, reader, true)
  598. case "STORE":
  599. s.store(session, args, nub, conn, reader)
  600. case "CLOSE":
  601. s.cclose(session, args, nub, conn, reader)
  602. case "EXPUNGE":
  603. s.expunge(session, args, nub, conn, reader)
  604. case "EXAMINE":
  605. s.examine(session, args, nub, conn, reader)
  606. case "SUBSCRIBE":
  607. s.subscribe(session, args, nub, conn, reader)
  608. case "UNSUBSCRIBE":
  609. s.unsubscribe(session, args, nub, conn, reader)
  610. case "LSUB":
  611. s.lsub(session, args, nub, conn, reader)
  612. case "STATUS":
  613. s.status(session, args, nub, conn, reader)
  614. case "CHECK":
  615. s.check(session, args, nub, conn, reader)
  616. case "SEARCH":
  617. s.search(session, args, nub, conn, reader)
  618. case "COPY":
  619. s.copy(session, args, nub, conn, reader)
  620. case "NOOP":
  621. s.noop(session, args, nub, conn, reader)
  622. case "LOGIN":
  623. s.login(session, args, nub, conn, reader)
  624. case "LOGOUT":
  625. s.logout(session, args, nub, conn, reader)
  626. case "UNSELECT":
  627. s.unselect(session, args, nub, conn, reader)
  628. case "IDLE":
  629. s.idle(session, args, nub, conn, reader)
  630. default:
  631. s.custom(session, cmd, args, nub, conn, reader)
  632. }
  633. }
  634. func (s *Server) handleClient(conn net.Conn) {
  635. slog.Debug("Imap conn")
  636. defer func() {
  637. if conn != nil {
  638. _ = conn.Close()
  639. }
  640. }()
  641. session := &Session{
  642. Conn: conn,
  643. Status: UNAUTHORIZED,
  644. AliveTime: time.Now(),
  645. }
  646. if s.TlsEnabled && s.TlsConfig != nil {
  647. session.InTls = true
  648. }
  649. // 检查连接是否超时
  650. if s.ConnectAliveTime != 0 {
  651. go func() {
  652. for {
  653. if time.Now().Sub(session.AliveTime) >= s.ConnectAliveTime {
  654. if session.Conn != nil {
  655. write(session.Conn, "* BYE AutoLogout; idle for too long", "")
  656. _ = session.Conn.Close()
  657. }
  658. session.Conn = nil
  659. session.IN_IDLE = false
  660. return
  661. }
  662. time.Sleep(3 * time.Second)
  663. }
  664. }()
  665. }
  666. reader := bufio.NewReader(conn)
  667. write(conn, fmt.Sprintf(`* OK [CAPABILITY IMAP4 IMAP4rev1 AUTH=LOGIN] PMail Server ready%s`, eol), "")
  668. for {
  669. rawLine, err := reader.ReadString('\n')
  670. if err != nil {
  671. if conn != nil {
  672. _ = conn.Close()
  673. }
  674. session.Conn = nil
  675. session.IN_IDLE = false
  676. return
  677. }
  678. session.AliveTime = time.Now()
  679. s.doCommand(session, rawLine, conn, reader)
  680. }
  681. }
  682. // cuts the line into command and arguments
  683. func getCommand(line string) (string, string, string) {
  684. line = strings.Trim(line, "\r \n")
  685. cmd := strings.SplitN(line, " ", 3)
  686. if len(cmd) == 1 {
  687. return "", "", ""
  688. }
  689. if len(cmd) == 3 {
  690. if strings.ToTitle(cmd[1]) == "UID" {
  691. args := strings.SplitN(cmd[2], " ", 2)
  692. if len(args) >= 2 {
  693. return cmd[0], strings.ToTitle(cmd[1]) + " " + strings.ToTitle(args[0]), args[1]
  694. }
  695. }
  696. return cmd[0], strings.ToTitle(cmd[1]), cmd[2]
  697. }
  698. return cmd[0], strings.ToTitle(cmd[1]), ""
  699. }
  700. func getSafeArg(args []string, nr int) string {
  701. if nr < len(args) {
  702. return args[nr]
  703. }
  704. return ""
  705. }
  706. func showSucc(w io.Writer, msg, nub string) {
  707. if msg == "" {
  708. write(w, fmt.Sprintf("%s OK success %s", nub, eol), nub)
  709. } else {
  710. write(w, fmt.Sprintf("%s %s %s", nub, msg, eol), nub)
  711. }
  712. }
  713. func showSuccWithData(w io.Writer, data []string, msg string, nub string) {
  714. content := ""
  715. for _, datum := range data {
  716. content += fmt.Sprintf("%s%s", datum, eol)
  717. }
  718. content += fmt.Sprintf("%s OK %s%s", nub, msg, eol)
  719. write(w, content, nub)
  720. }
  721. func showBad(w io.Writer, err string, nub string) {
  722. if nub == "" {
  723. nub = "*"
  724. }
  725. if err == "" {
  726. write(w, fmt.Sprintf("%s BAD %s", nub, eol), nub)
  727. return
  728. }
  729. write(w, fmt.Sprintf("%s BAD %s%s", nub, err, eol), nub)
  730. }
  731. func showNo(w io.Writer, msg string, nub string) {
  732. write(w, fmt.Sprintf("%s NO %s%s", nub, msg, eol), nub)
  733. }
  734. func paramsErr(w io.Writer, commend string, nub string) {
  735. write(w, fmt.Sprintf("* BAD %s parameters! %s", commend, eol), nub)
  736. }
  737. func write(w io.Writer, content string, nub string) {
  738. if !strings.HasSuffix(content, eol) {
  739. log.Errorf("Error:返回结尾错误 %s", content)
  740. }
  741. log.Debugf("Imap Out:\t |%s", content)
  742. fmt.Fprintf(w, content)
  743. }