1#!/bin/sh -norc 2# 3# MIMEPARTS.SH 4# Author: "Garen Erdoisa" <scamper@trisk.com> 5# Licence: GNU GPL 6# Last Update: 8/14/2011 7# 8# Synopsis: 9# This /bin/sh custom shell script written on behalf of the SpamBouncer project 10# and as such is donated by the Author to the SpamBouncer project. 11# 12# This software is specifically designed to work in conjuction with and as a part of 13# SpamBouncer 3.0 or higher, it is not intended for any other use. 14# 15# Use of this code with any other software will likely not work without major modifications. 16# 17# For a description of base64 encoding see: 18# RFC 1521 http://www.ietf.org/rfc/rfc1521.txt Para: 5.2 19# 20# Expecting the following exported variables 21# export SED ECHO NL DECODEBASE64 SBLOGLEVEL GREP EGREP SBDIR SPACES_TABS_TO_SPACES MESSAGETMPDIR WC SBPID DATE HOST LOGFILE SBLOGFILE SBHEADERS HASHCOMMAND 22# 23# Expecting the following command line arguments: 24# 25# These are local variables, not global. They don't belong at all in sb-config-default.rc 26# and if you define them there it will have no effect. 27# Don't change these or something will likely break. 28thisfilename=$0 29sourcefilename="$1" 30OUTLINE="$2" 31#PART="$3" 32PART=1 33RECURSELEVEL="$4" 34RECURSELIMIT="$5" 35LOCALBOUNDARY="$6" 36 37# Four /bin/sh functions: splitparts(), greplocalparts(), getlinepairs(), dbecho() 38# are defined by this file. 39# 40# The dot at the begining of the line is diliberate. 41# Don't change it or it will break this script. 42# The dot causes the shell_functions.sh to be read into the current 43# shell environment as if it were a part of this file. 44. ${SBDIR}/functions/shell_functions.sh 45 46# dbecho is a function defined in shell_functions.sh that will only 47# echo the text if the SBLOGLEVEL >= ARG1 48# It's for debugging. 49 50# Debug info 51if ! [ "${OUTLINE}" = "1" ]; then 52 dbecho 7 "Debug[${SBLOGLEVEL}]: [${OUTLINE}]: Recursive entry into file: ${thisfilename}" 53fi 54#dbecho 8 "Debug[${SBLOGLEVEL}]: MESSAGETMPDIR=\"${MESSAGETMPDIR}\"" 55#dbecho 8 "Debug[${SBLOGLEVEL}]: sourcefilename=${MESSAGETMPDIR}/${sourcefilename}" 56#dbecho 8 "Debug[${SBLOGLEVEL}]: OUTLINE=${OUTLINE}" 57#dbecho 8 "Debug[${SBLOGLEVEL}]: RECURSELEVEL=${RECURSELEVEL}" 58#dbecho 8 "Debug[${SBLOGLEVEL}]: RECURSELIMIT=${RECURSELIMIT}" 59#dbecho 8 "Debug[${SBLOGLEVEL}]: LOCALBOUNDARY=${LOCALBOUNDARY}" 60 61# Unless exported from the calling process, all other variables should be local to this routine. 62dbecho 8 "Debug[${SBLOGLEVEL}]: Recursion level: ${RECURSELEVEL} of ${RECURSELIMIT}; Outline Level: ${OUTLINE}" 63 64# Outline tracks the current outline level we are at in the parse. 65# dbecho 8 "Debug[${SBLOGLEVEL}]: Outline: \"${OUTLINE}\"" 66 67filename="${sourcefilename}" 68LOCALPARTS=0 69LOCALLINEPAIRS=0 70 71# LOCALPARTS 72dbecho 7 "Parsing: ${MESSAGETMPDIR}/${filename} LOCALBOUNDARY=${LOCALBOUNDARY}" 73 74greplocalparts "${MESSAGETMPDIR}/${filename}" "${LOCALBOUNDARY}" 75dbecho 7 "Debug[${SBLOGLEVEL}]: LOCALPARTS=${LOCALPARTS}" 76 77VALIDATEPARTBEGIN=`${ECHO} "${LOCALPARTS}" |${SED} -e '1!d;s/^\([0-9]\{1,\}:\)\(--\)\(.\{1,\}\)$/\2/'` 78VALIDATEPARTENDING=`${ECHO} "${LOCALPARTS}" |${SED} -e '$!d;s/^\([0-9]\{1,\}:--\)\(.\{1,\}\)\(--\)$/\3/'` 79if [ "${VALIDATEPARTBEGIN}" = "--" ] && [ "${VALIDATEPARTENDING}" = "--" ]; then 80 VALIDPART=yes 81else 82 VALIDPART=no 83 dbecho 8 "Debug[${SBLOGLEVEL}]: Mime part was not properly closed. Attempting repair." 84 if ! [ "${VALIDATEPARTENDING}" = "--" ]; then 85 (${CAT} ${MESSAGETMPDIR}/${filename};${ECHO} "";${ECHO} "--${LOCALBOUNDARY}--";${ECHO} "") >>${MESSAGETMPDIR}/${filename}_repair 86 fi 87 88 greplocalparts "${MESSAGETMPDIR}/${filename}_repair" "${LOCALBOUNDARY}" 89 dbecho 7 "Debug[${SBLOGLEVEL}]: repair LOCALPARTS=${LOCALPARTS}" 90 VALIDATEPARTBEGIN=`${ECHO} "${LOCALPARTS}" |${SED} -e '1!d;s/^\([0-9]\{1,\}:\)\(--\)\(.\{1,\}\)$/\2/'` 91 VALIDATEPARTENDING=`${ECHO} "${LOCALPARTS}" |${SED} -e '$!d;s/^\([0-9]\{1,\}:--\)\(.\{1,\}\)\(--\)$/\3/'` 92 93 if [ "${VALIDATEPARTBEGIN}" = "--" ] && [ "${VALIDATEPARTENDING}" = "--" ]; then 94 VALIDPART=yes 95 dbecho 8 "Debug[${SBLOGLEVEL}]: Mime part sucessfully closed. Continuing." 96 ${MV} ${MESSAGETMPDIR}/${filename}_repair ${MESSAGETMPDIR}/${filename} 97 else 98 dbecho 8 "Debug[${SBLOGLEVEL}]: Mime part was not properly opened. Repair unsucessful, giving up." 99 fi 100fi 101 102dbecho 8 "Debug[${SBLOGLEVEL}]: OUTLINE=${OUTLINE} VALIDPART=${VALIDPART}" 103if [ "${VALIDPART}" = "yes" ];then 104 # LOCALLINEPAIRS 105 # dbecho 8 "Debug[${SBLOGLEVEL}]: getlinepairs \"${LOCALPARTS}\"" 106 getlinepairs "${LOCALPARTS}" 107 dbecho 8 "Debug[${SBLOGLEVEL}]: LOCALLINEPAIRS=${LOCALLINEPAIRS}" 108 #Commented this out because I converted the LOCALLINEPAIRS to be all on one line. 109 #COUNT=`${ECHO} "${LOCALLINEPAIRS}" |grep -En "" |${SED} -nre '$s/^([0-9]+):(.+)$/\1/p'` 110 #dbecho 8 "Debug[${SBLOGLEVEL}]: COUNT=$COUNT" 111 for i in ${LOCALLINEPAIRS} 112 do 113 dbecho 8 "Debug[${SBLOGLEVEL}]: splitparts \"${MESSAGETMPDIR}/MIME_${OUTLINE}\" \"${PART}\" \"$i\"" 114 # This function creates the body/header files 115 splitparts "${MESSAGETMPDIR}/MIME_${OUTLINE}" "${PART}" "$i" 116 #Check part header to see if we need to recurse here 117 dbecho 8 "Debug[${SBLOGLEVEL}]: checkpart \"${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header\"" 118 # some boundary tags are quoted. 119 checkpart=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 120 ${SED} -e ' 121 /^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: [Mm][Uu][Ll][Tt][Ii][Pp][Aa][Rr][Tt]\/\(.\{1,\}\);\( \)\?[Bb][Oo][Uu][Nn][Dd][Aa][Rr][Yy]=".\{1,\}"\(;.*\)\?$/!d 122 s/^\([C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: [Mm][Uu][Ll][Tt][Ii][Pp][Aa][Rr][Tt]\/.\{1,\}; \?[Bb][Oo][Uu][Nn][Dd][Aa][Rr][Yy]="\)\([^"]\{1,\}\)\("\)\(;.*\)\?$/\2/ 123 '` 124 # some boundary tags are not quoted. 125 # Note: unquoted boundary tags can not contain ; or : 126 if [ "${checkpart}" = "" ]; then 127 checkpart=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 128 ${SED} -e ' 129 /^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: [Mm][Uu][Ll][Tt][Ii][Pp][Aa][Rr][Tt]\/\(.\{1,\}\);\( \)\?[Bb][Oo][Uu][Nn][Dd][Aa][Rr][Yy]=[^"]\{1,\}\(;.*\)\?$/!d 130 s/^\([C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: [Mm][Uu][Ll][Tt][Ii][Pp][Aa][Rr][Tt]\/.\{1,\}; \?[Bb][Oo][Uu][Nn][Dd][Aa][Rr][Yy]=\)\([^";:]\{1,\}\)\(;.*\)\?$/\2/ 131 '` 132 fi 133 # Check for Content-Type headers = text or html or quoted printable 134 # if such parts are found, and are base64 encoded, then decode them. 135 # and/or calculate the sha1 hash of them. 136 # I'm not doing anything with quoted printable or 8bit text at this time. 137 # 138 # Note: For future consideration, test parts that claim 7bit encoding to see if they 139 # are actually 7bit. If not, the encoding tag is lying, which could be a spam indicator. 140 # 141 # Content-Type: text/(plain|html) 142 checkcontentype_text_plain_html=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 143 ${SED} -e ' 144 /^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: [Tt][Ee][Xx][Tt]\/\([Pp][Ll][Aa][Ii][Nn]\|[Hh][Tt][Mm][Ll]\)\(;.*\)\?$/!d 145 '` 146 if ! [ "${checkcontentype_text_plain_html}" = "" ]; then 147 dbecho 8 "Debug[${SBLOGLEVEL}]: checkcontentype_text_plain_html=\"${checkcontentype_text_plain_html}\"" 148 fi 149 # Content-Type: application/(.+) 150 checkcontentype_application=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 151 ${SED} -e ' 152 /^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: [Aa][Pp][Pp][Ll][Ii][Cc][Aa][Tt][Ii][Oo][Nn]\/.\{1,\}\(;.*\)\?$/!d 153 '` 154 if ! [ "${checkcontentype_application}" = "" ]; then 155 dbecho 8 "Debug[${SBLOGLEVEL}]: checkcontentype_application=\"${checkcontentype_application}\"" 156 fi 157 # Content-Type: image/(.+) 158 checkcontentype_image=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 159 ${SED} -e ' 160 /^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: [Ii][Mm][Aa][Gg][Ee]\/.\{1,\}\(;.*\)\?$/!d 161 '` 162 if ! [ "${checkcontentype_image}" = "" ]; then 163 dbecho 8 "Debug[${SBLOGLEVEL}]: checkcontentype_image=\"${checkcontentype_image}\"" 164 fi 165 166 # Content-Transfer-Encoding: base64 167 checkencodingbase64=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 168 ${SED} -e ' 169 /^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Rr][Aa][Nn][Ss][Ff][Ee][Rr]-[Ee][Nn][Cc][Oo][Dd][Ii][Nn][Gg]: [Bb][Aa][Ss][Ee]64\(;.*\)\?$/!d 170 '` 171 if ! [ "${checkencodingbase64}" = "" ]; then 172 dbecho 8 "Debug[${SBLOGLEVEL}]: Found base64 encoding tag in MIME_${OUTLINE}_${PART}.header" 173 checkcontent_disposition_attachment_filename=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 174 ${SED} -e '/^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Dd][Ii][Ss][Pp][Oo][Ss][Ii][Tt][Ii][Oo][Nn]: [Aa][Tt][Tt][Aa][Cc][Hh][Mm][Ee][Nn][Tt].*[; ]\?[Ff][Ii][Ll][Ee][Nn][Aa][Mm][Ee]=.\{1,\}\(;.*\)\?$/!d' |\ 175 ${SED} -e 's/^\([C][Oo][Nn][Tt][Ee][Nn][Tt]-[Dd][Ii][Ss][Pp][Oo][Ss][Ii][Tt][Ii][Oo][Nn]: [Aa][Tt][Tt][Aa][Cc][Hh][Mm][Ee][Nn][Tt].*[; ]\?[Ff][Ii][Ll][Ee][Nn][Aa][Mm][Ee]=\)\(.\{1,\}\)\(\(;.*\)\?\)$/\2/' |\ 176 ${SED} -e 's/^\("\)\(.\{1,\}\)\("\)$/\2/' 177 ` 178 if ! [ "${checkcontent_disposition_attachment_filename}" = "" ];then 179 dbecho 8 "Debug[${SBLOGLEVEL}]: checkcontent_disposition_attachment_filename=\"${checkcontent_disposition_attachment_filename}\"" 180 fi 181 checkcontent_type_name=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 182 ${SED} -e '/^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: .*[; ]\?[Nn][Aa][Mm][Ee]=.\{1,\}\(;.*\)\?$/!d' |\ 183 ${SED} -e 's/^\([C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Yy][Pp][Ee]: .*[; ]\?[Nn][Aa][Mm][Ee]=\)\(.\{1,\}\)\(\(;.*\)\?\)$/\2/' |\ 184 ${SED} -e 's/^\("\)\(.\{1,\}\)\("\)$/\2/' 185 ` 186 if ! [ "${checkcontent_type_name}" = "" ];then 187 dbecho 8 "Debug[${SBLOGLEVEL}]: checkcontent_type_name=\"${checkcontent_type_name}\"" 188 fi 189 fi 190 191 # Content-Transfer-Encoding: 7bit 192 checkencoding7bit=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header |\ 193 ${SED} -e ' 194 /^[C][Oo][Nn][Tt][Ee][Nn][Tt]-[Tt][Rr][Aa][Nn][Ss][Ff][Ee][Rr]-[Ee][Nn][Cc][Oo][Dd][Ii][Nn][Gg]: \?.*7[Bb][Ii][Tt]\(;.*\)\?$/!d 195 '` 196 if ! [ "${checkencoding7bit}" = "" ]; then 197 dbecho 8 "Debug[${SBLOGLEVEL}]: Found 7bit encoding tag in MIME_${OUTLINE}_${PART}.header" 198 # dbecho 8 "Debug[${SBLOGLEVEL}]: ${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body |${TR} -d \"\000-\177\" |${WC} -c" 199 checkcontent7bit=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body |${TR} -d "\000-\177" |${WC} -c` 200 if ! [ "${checkcontent7bit}" = "0" ]; then 201 dbecho 8 "Debug[${SBLOGLEVEL}]: 8bit byte count=${checkcontent7bit} MIME_${OUTLINE}_${PART}.body is not 7bit!" 202 # This code mimics the following for SpamBouncer logging: 203 # SBLOG="C3N: MIME Part ${OUTLINE}_${PART} claims 7bit encoding but has 8bit content" 204 # INCLUDERC=${SBDIR}/functions/loglevel.rc 205 # Note the header in the log 206 dbecho 3 "SBNote: MIME Part ${OUTLINE}_${PART} claims 7bit encoding but has 8bit content" 207 if [ "${SBHEADERS}" = "COMPLETE" ] || [ "${SBHEADERS}" = "BRIEF" ]; then 208 # Add the header to the email. 209 ${ECHO} "X-SBNote: MIME Part ${OUTLINE}_${PART} claims 7bit encoding but has 8bit content" >>${MESSAGETMPDIR}/sbheaders-created-during-autopsy 210 fi 211 else 212 dbecho 8 "Debug[${SBLOGLEVEL}]: Confirmed: 8bit byte count=${checkcontent7bit} MIME_${OUTLINE}_${PART}.body is 7bit." 213 fi 214 fi 215 216 # This is where we decide what to include in the Message Body Autopsy. The rest will be ignored. 217 218 # Pick up the part header files if any and include them in the autopsy so 219 # SpamBouncer can check the language charset headers, and other Content- headers. 220 if [ -f ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header ]; then 221 dbecho 7 "Debug[${SBLOGLEVEL}]: Including file: ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header" 222 ${ECHO} "${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.header" >>${MESSAGETMPDIR}/plain_body_files_to_parse.txt 223 fi 224 # If the Content-Type: mime part header claims the part is text/html, then include it in the autopsy. Decode base64 if necessary. 225 if ! [ "${checkcontentype_text_plain_html}" = "" ]; then 226 if ! [ "${checkencodingbase64}" = "" ]; then 227 #dbecho 8 "Debug[${SBLOGLEVEL}]: ${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body |${DECODEBASE64} >${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.plain" 228 ${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body |\ 229 ${DECODEBASE64} |\ 230 ${SED} -e 's/^From /\\From /;s/^\.$/\\./' >${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.plain 231 dbecho 7 "Debug[${SBLOGLEVEL}]: Including file: ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.plain" 232 ${ECHO} "${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.plain" >>${MESSAGETMPDIR}/plain_body_files_to_parse.txt 233 else 234 #dbecho 8 "Debug[${SBLOGLEVEL}]: ${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body >${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.plain" 235 ${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body |\ 236 ${SED} -e 's/^From /\\From /;s/^\.$/\\./' >${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.plain 237 dbecho 7 "Debug[${SBLOGLEVEL}]: Including file: ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.plain" 238 ${ECHO} "${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.plain" >>${MESSAGETMPDIR}/plain_body_files_to_parse.txt 239 fi 240 fi 241 # If the Content-Type: mime part header claims the part is an application or image then 242 # Calculate the sha1 hash of the MIME body part or if the part is base64 encoded, 243 # calculate the sha1 hash of the decoded body part. 244 # This hash could be checked against or added to a database of spammy sha1 hash's. 245 # or against a databse of sha1 hashes that have been whitelisted. 246 # such as might exist for bank logo .jpg's, trademark loogo's etc. 247 # ie: ~/.sbSpammyHashCache 248 if ! [ "${checkcontentype_application}" = "" ] || \ 249 ! [ "${checkcontentype_image}" = "" ] || \ 250 ! [ "${checkcontent_disposition_attachment_filename}" = "" ] || \ 251 ! [ "${checkcontent_type_name}" = "" ];\ 252 then 253 if ! [ "${checkencodingbase64}" = "" ]; then 254 (((${ECHO} "base64 decoded sha1 hash=\"<";\ 255 ${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body |\ 256 ${DECODEBASE64} |\ 257 ${HASHCOMMAND};\ 258 ${ECHO} ">\"")|\ 259 ${TR} -d '\012\015');\ 260 ${ECHO} "") \ 261 >${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.hash 262 dbecho 7 "Debug[${SBLOGLEVEL}]: Including file: ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.hash" 263 ${ECHO} "${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.hash" \ 264 >>${MESSAGETMPDIR}/plain_body_files_to_parse.txt 265 else 266 (((${ECHO} "sha1 hash=\"<";\ 267 ${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body |\ 268 ${HASHCOMMAND};\ 269 ${ECHO} ">\"")|\ 270 ${TR} -d '\012\015');\ 271 ${ECHO} "") \ 272 >${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.hash 273 dbecho 7 "Debug[${SBLOGLEVEL}]: Including file: ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.hash" 274 ${ECHO} "${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.hash" \ 275 >>${MESSAGETMPDIR}/plain_body_files_to_parse.txt 276 fi 277 hash=`${CAT} ${MESSAGETMPDIR}/MIME_${OUTLINE}_${PART}.body.hash |\ 278 ${SED} -re 's/^(.*sha1 hash=")([<].+[>])"$/\2/'` 279 dbecho 8 "Debug[${SBLOGLEVEL}]: hash=\"${hash}\"" 280 check_spammy_mimepart_hash='' 281 if [ -f ${HOME}/.sbSpammyHashCache ]; then 282 # dbecho 8 "Debug[${SBLOGLEVEL}]: ${GREP} -x \"${hash}\" ${HOME}/.sbSpammyHashCache" 283 # 284 # Note: this code could be adjusted to check a dns blocklist for a spammy hash instead of a file 285 # ie: something like this: 286 # check_spammy_mimepart_hash=`${HOST} ${hash}.hashcheck.dnsbl.example.org` 287 # where 127.0.0.2 = hash signature of a mime part found in spamtraps 288 # 127.0.0.3 = hash signature of a known virus/trojen or other dangerous attachment 289 # 127.0.0.4 = hash signature of a known good logo/trademark, possible spam victim. 290 # 291 # Check a file of sha1 signatures of mime parts found in spam. 292 # special case: 293 # Note: da39a3ee5e6b4b0d3255bfef95601890afd80709 is the sha1 hash of a zero byte or NULL message 294 # ie: echo -ne "" |openssl base64 -d |openssl sha1 295 # if that is the result of the decode, then ignore it. 296 # The hash is likely the result of a previously defanged message. 297 # probably from a virus filter that removed the part, but otherwise 298 # left the mime structure intact then delivered the defanged message. 299 if ! [ "${hash}" = "<da39a3ee5e6b4b0d3255bfef95601890afd80709>" ]; then 300 check_spammy_mimepart_hash=`${GREP} -x "${hash}" ${HOME}/.sbSpammyHashCache` 301 fi 302 # dbecho 8 "Debug[${SBLOGLEVEL}]: check_spammy_mimepart_hash=\"${check_spammy_mimepart_hash}\"" 303 fi 304 if ! [ "${check_spammy_mimepart_hash}" = "" ]; then 305 # This code mimics the following for SpamBouncer logging: 306 # SBLOG="C3T: Spammy Hash (MIME part ${OUTLINE}_${PART})" 307 # INCLUDERC=${SBDIR}/functions/loglevel.rc 308 dbecho 4 "Found sha1 hash \"${hash}\" cached." 309 dbecho 3 "SBPattern: Spammy Hash (MIME part ${OUTLINE}_${PART})" 310 if [ "${SBHEADERS}" = "COMPLETE" ] || [ "${SBHEADERS}" = "BRIEF" ]; then 311 ${ECHO} "X-SBPattern: Spammy Hash (MIME part ${OUTLINE}_${PART})" >>${MESSAGETMPDIR}/sbheaders-created-during-autopsy 312 fi 313 fi 314 fi 315 316 # Are we done extracting mime parts? If not then recurse to extract the next set of MIME parts in outline format. 317 # This is where this file calls itself to do this magic. 318 if ! [ "${checkpart}" = "" ]; then 319 dbecho 8 "Debug[${SBLOGLEVEL}]: checkpart=\"${checkpart}\"" 320 if ! [ "${RECURSELEVEL}" -ge "${RECURSELIMIT}" ]; then 321 # dbecho 8 "Debug[${SBLOGLEVEL}]: ${SBDIR}/functions/mimeparts.sh MIME_${OUTLINE}_${PART} ${OUTLINE}_${PART} $[RECURSELEVEL+1] ${RECURSELIMIT} ${checkpart}" 322 # This is where we do the recursion if it's needed. 323 ${SBDIR}/functions/mimeparts.sh "MIME_${OUTLINE}_${PART}" "${OUTLINE}_${PART}" "${PART}" "$[RECURSELEVEL+1]" "${RECURSELIMIT}" "${checkpart}" 324 dbecho 7 "Debug[${SBLOGLEVEL}]: [${OUTLINE}_${PART}] Recursive exit from file: ${thisfilename}" 325 else 326 dbecho 3 "MIME Recurse limit reached: RECURSELEVEL=${RECURSELEVEL} >= RECURSELIMIT=${RECURSELIMIT}" 327 fi 328 fi 329 PART=$[PART+1] 330 done 331fi 332