/lib/mailUtils.tcl

http://github.com/maxcom/tklor · TCL · 170 lines · 135 code · 9 blank · 26 comment · 12 complexity · beeb449d23bbbe3d4c649a275237a4a4 MD5 · raw file

  1. ############################################################################
  2. # Copyright (C) 2008 Alexander Galanin <gaa.nnov@mail.ru> #
  3. # #
  4. # This program is free software: you can redistribute it and/or modify #
  5. # it under the terms of the GNU Lesser General Public License as #
  6. # published by the Free Software Foundation, either version 3 of the #
  7. # License, or (at your option) any later version. #
  8. # #
  9. # This program is distributed in the hope that it will be useful, #
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of #
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
  12. # GNU General Public License for more details. #
  13. # #
  14. # You should have received a copy of the GNU Lesser GNU General Public #
  15. # License along with this program. #
  16. # If not, see <http://www.gnu.org/licenses/>. #
  17. ############################################################################
  18. package provide mailUtils 1.0
  19. package require Tcl 8.4
  20. package require htmlparse 1.1
  21. namespace eval mailUtils {
  22. namespace export \
  23. makeReplyHeader \
  24. quoteText \
  25. makeReply
  26. #
  27. # makeReply - Make header with "Re:" prefix
  28. #
  29. proc makeReplyHeader {header} {
  30. set re {^re(?:\^(\d+)|()):\s+}
  31. set count 0
  32. while { [ regexp -nocase -lineanchor -- $re $header dummy c ] != 0 } {
  33. if { $c == "" } {
  34. set c 1
  35. }
  36. incr count $c
  37. regsub -nocase -lineanchor -- $re $header {} header
  38. }
  39. if { $count != 0 } {
  40. return "Re^[ expr $count + 1 ]: $header"
  41. } else {
  42. return "Re: $header"
  43. }
  44. }
  45. #
  46. # quoteText - Put text into ">" quotes
  47. #
  48. proc quoteText {text} {
  49. set res ""
  50. foreach line [ split $text "\n" ] {
  51. if { [ string trim $line ] != "" } {
  52. if { [ string compare -length 1 $line ">" ] == 0 } {
  53. lappend res ">$line"
  54. } else {
  55. lappend res "> $line"
  56. }
  57. }
  58. }
  59. return [ join $res "\n\n" ]
  60. }
  61. #
  62. # htmlToText - convert LOR-style HTML to text
  63. #
  64. proc htmlToText {text} {
  65. foreach {re s} {
  66. {<img src="/\w+/\w+/votes\.gif"[^>]*>} "\[\\&\]"
  67. "<img [^>]*?>" "[image]"
  68. "<!--.*?-->" ""
  69. "<tr>" "\n"
  70. "</tr>" ""
  71. "</{0,1}table>" ""
  72. "</{0,1}td(?: colspan=\\d+){0,1}>" " "
  73. "</{0,1}pre>" ""
  74. "\n<br>" "\n"
  75. "<br>\n" "\n"
  76. "<br>" "\n"
  77. "<p>" "\n"
  78. "</p>" ""
  79. "<a href=\"([^\"]+)\"[^>]*>[^<]*</a>" "\\1"
  80. "</{0,1}i>" ""
  81. "</{0,1}(?:u|o)l>" ""
  82. "<li>" "\n * "
  83. "</li>" ""
  84. "\n{3,}" "\n\n" } {
  85. regsub -all -nocase -- $re $text $s text
  86. }
  87. return [ ::htmlparse::mapEscapes $text ]
  88. }
  89. #
  90. # makeReplyToMessage - Make reply to specified message
  91. #
  92. # letter - original letter
  93. # from - string to substitute into From header
  94. # headers - (optional) additional headers
  95. #
  96. proc makeReplyToMessage {letter from {headers ""}} {
  97. set res ""
  98. array set tmp {
  99. From ""
  100. To ""
  101. In-Reply-To ""
  102. Message-ID ""
  103. Subject ""
  104. Content-Type "text/html"
  105. body ""
  106. }
  107. foreach {h v} [ concat $letter $headers ] {
  108. if { [ lsearch [ array names tmp ] $h ] >= 0 } {
  109. set tmp($h) $v
  110. } else {
  111. lappend res $h $v
  112. }
  113. }
  114. lappend res From $from
  115. lappend res To $tmp(From)
  116. lappend res In-Reply-To $tmp(Message-ID)
  117. if { $tmp(Content-Type) == "text/html" } {
  118. set subj [ htmlToText $tmp(Subject) ]
  119. set body [ htmlToText $tmp(body) ]
  120. } else {
  121. set subj $tmp(Subject)
  122. set body $tmp(body)
  123. }
  124. #TODO: will be removed in v1.2
  125. lappend res Subject [ makeReplyHeader $subj ]
  126. lappend res Content-Type "text/plain"
  127. lappend res body [ quoteText $body ]
  128. array unset tmp
  129. return $res
  130. }
  131. #
  132. # getMailHeaders - Get specified headers from letter as list.
  133. # If header does not present in text, it will be
  134. # substituded as ""
  135. #
  136. # letter - message to process
  137. # headers - list of headers
  138. #
  139. proc getMailHeaders {letter headers} {
  140. array set arr ""
  141. foreach h $headers {
  142. set arr($h) ""
  143. }
  144. foreach {h v} $letter {
  145. if { [ lsearch -exact $headers $h ] >= 0 } {
  146. set arr($h) $v
  147. }
  148. }
  149. set res ""
  150. foreach h $headers {
  151. lappend res $arr($h)
  152. }
  153. array unset arr
  154. return $res
  155. }
  156. }