IZ*ONE Mail Shelter (IZMS)๋ ์์ด์ฆ์ ํ๋ผ์ด๋น ๋ฉ์ผ ์ฑ์์ ๋ฐ์ ๋ฉ์ผ๋ค์ HTML ํ์์ผ๋ก ๋ก์ปฌ์ ๋ค์ด๋ก๋ํ๋ ํ์ด์ฌ ํ๋ก๊ทธ๋จ์ ๋๋ค.
๋ณ๋ ฌ ๋ค์ด๋ก๋๋ฅผ ์ง์ํ์ฌ 1์ด๋น 50๊ฐ ์ด์์ ๋ฉ์ผ์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.
์ฒซ ์คํ ํ์๋ ๋ก์ปฌ์ ์ค์ ํ ๋ฐฑ์
๋๋ ํ ๋ฆฌ์ ์๋ฒ ๋ฉ์ผํจ๊ณผ์ ์ฐจ์ด๋ฅผ ๋น๊ตํ์ฌ ์๋ก์ด ๋ฉ์ผ๋ง ์ถ๊ฐ์ ์ผ๋ก ๋ค์ด๋ก๋ํฉ๋๋ค.
๋ณธ ๋ฆฌํฌ๋ ์์ด์ฆ์ ํ๋ผ์ด๋น ๋ฉ์ผ ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ IZONEMail
ํด๋์ค์ ๊ทธ๊ฒ์ ์ด์ฉํ ๋ฐฑ์
์คํฌ๋ฆฝํธ izms.py
๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
2021.05.29
- HKT48 Mail ๋์ ์ ๋ฐ์ดํธ
2021.04.07
- ๋ณ๋ ฌ ๋ค์ด๋ก๋ ์ง์ (
max_workers
์ต์ )
2021.04.05
- ๋ชจ๋ ํ์ผ์ root path์ธ
destination
์ต์ ์ถ๊ฐ - ํ๋กํ ์ด๋ฏธ์ง ๋ณ๋ ์ ์ฅ (
profile_image_path
์ต์ ) embed_css
,image_to_base64
์ต์ ์ ๊ฑฐ (HTML์ ์๋ฒ ๋ฉ ๋ฐฉ๋ฒ์ Appendix ์ฐธ์กฐ)- ์ค์ ์์ path๋ ๋ชจ๋ ์ ๋๊ฒฝ๋ก๋ก ๋ณ๊ฒฝ
subject
์์ ํ์ผ๋ช ์ ๋ค์ด๊ฐ ์ ์๋ ํน์๋ฌธ์ ์ ๊ฑฐ
2021.03.22
- ํ๊ตญ์ด README ์ถ๊ฐ
- ์ค์ ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝ
user_settings.json
โconfig.json
- ๋ฉ์ผ ๋ค์ด๋ก๋ ์์ ๋ณ๊ฒฝ (์ ์ผ ์ค๋๋ ๋ฉ์ผ๋ถํฐ)
- Customizable ๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก
- Standalone bundle ์ ๊ณต
- CSS, ์ฌ์ง ๋ณ๋ ์ ์ฅ ์ต์
- ๋ฐฑ์ ๋๋ ํ ๋ฆฌ๋ฅผ ์ค์บํ์ง ์๊ณ ๋ณ๋์ INDEX๋ฅผ ํตํด ๋ค์ด๋ก๋ํ ๋ฉ์ผ ๊ด๋ฆฌ
- Verbose error logs
IZMS๋ ๋ค์ ํ๊ฒฝ์์ ํ ์คํธ ๋์์ต๋๋ค.
- Python 3.9~
- macOS 10.15~
- Windows 10
- Ubuntu 20.04 64-bit
๋ฏธ๋ฆฌ ๋น๋๋ ์คํ ํ์ผ์ ์ด์ฉํ์ฌ ํ์ด์ฌ์ด๋ ๊ธฐํ ์ข ์์ฑ์ ์ค์นํ์ง ์๊ณ IZMS๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
IZMS ๋ฆด๋ฆฌ์ฆ ํ์ด์ง ์์ ์์ ์ ์ด์์ฒด์ ์ ๋ง๋ ๋ฒ์ ์ ๋ค์ด๋ฐ๊ณ ์์ถ์ ํ๋๋ค.
โ ๏ธ ๋ค์ด๋ฐ์ ๋ ๋ธ๋ผ์ฐ์ ์ ๋ฐ๋ผ ๊ฒฝ๊ณ ์ฐฝ์ด ๋จ๋ฉฐ ๋ค์ด๋ก๋๋์ง ์์ ์ ์์ต๋๋ค. ์ด๊ฒ์ IZMS ์คํํ์ผ์ด ์ธ์ฆ์๋ก ์๋ช ๋์ง ์์๊ธฐ ๋๋ฌธ์ด๋ฉฐ, '๊ณ์'์ ๋๋ฌ ๋ค์ด๋ก๋ ๋ฐ์ ์ ์์ต๋๋ค. ์๋ช ๋์ง ์์ ์คํํ์ผ์ ์ผ๋ถ ๋ฐฑ์ ํ๋ก๊ทธ๋จ์์ ๋ฐ์ด๋ฌ์ค๋ก ์ธ์ํ ์๋ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ๋ฐฑ์ ์์ ์์ธ ๋ฑ๋ก์ ํ๊ฑฐ๋ ๋ฐฉ๋ฒ2๋ก ์๋ํ์๊ธฐ ๋ฐ๋๋๋ค.
๐ข HKT48 Mail์ ๊ฒฝ์ฐ
config.json
์ด ์๋config_hkt48mail.json
์ ์์
{
// ...
"profile": {
"user-id": "์ ์ ID",
"access-token": "์ก์ธ์ค ํ ํฐ",
// ...
}
}
์คํ์ ์ํด์๋ ๋จผ์ ์ค์ ํ์ผ config.json
์ ์์ ํด์ผ ํฉ๋๋ค.
Charles, Wireshark, Burp Suite๋ฑ์ SSL ํจํท ์บก์ฒ ํด์ ์ด์ฉํ์ฌ ์์๋ธ ์์ ์ user-id
์ access-token
์ config.json
์ ์
๋ ฅํฉ๋๋ค.
์๋๋ user-id
, access-token
์ ์
๋ ฅํ ์์ ํ config.json
์ ์์์
๋๋ค.
Example - config.json
{
"bundle_id": "com.ca-smart.izonemail",
"destination": "incoming",
"mail_path": "/mail/{member_id}/{mail_id}.html",
"profile_image_path": "/",
"css_path": "/css",
"image_path": "/img",
"max_workers": 8,
"profile": {
"user-id": "57crzfhy4is0",
"access-token": "klcr55c7000k82f1603oa6al",
"os-type": "iOS",
"terms-version": "5",
"application-version": "1.2.3",
"application-language": "ko"
}
}
ํฐ๋ฏธ๋์ ์ด๊ณ ์์ถ์ ํผ ๊ฒฝ๋ก๋ก ์ด๋ํฉ๋๋ค. ์๋์ฐ์ ๊ฒฝ์ฐ ํฐ๋ฏธ๋์ powershell์ ์ถ์ฒํฉ๋๋ค.
> cd "IZMS ๊ฒฝ๋ก"
์ฑ์ ์คํํฉ๋๋ค.
> ./izms
> ./izms -c config_hkt48mail.json
๐ข HKT48 Mail๋ง ๋ฐฑ์ ํ๊ณ ์ ํ๋ ๊ฒฝ์ฐ
config_hkt48mail.json
ํ์ผ๋ช ์config.json
์ผ๋ก ๋ณ๊ฒฝ ํ ์๋ฌด๋ฐ ์ต์ ์์ด ์คํ์์ผ๋ ๋ฉ๋๋ค.
๋ง์ฝ user-id
๋ access-token
์ ์๋ชป ์
๋ ฅํ์ ๊ฒฝ์ฐ 401 Unauthorized ์๋ฌ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
๊ธฐ๋ณธ๊ฐ์ ๋ฐ๊พธ์ง ์์ผ๋ฉด ๋ฉ์ผ์ incoming/
ํด๋์ ์ ์ฅ๋ฉ๋๋ค.
> git clone https://github.com/coloriz/izms.git
> cd izone-mail-shelter
> pip install -r requirements.txt
๋ฐฉ๋ฒ1 ์ฐธ์กฐ.
> python izms.py
์ค์ ๊ธฐ๋ณธ๊ฐ์ ๋ณ๊ฒฝํ๊ธธ ์ํ๋ ๊ฒฝ์ฐ ๊ฐ์ด๋๋ฅผ ์ ํํ ์ฝ๊ณ ์งํํ์๊ธฐ ๋ฐ๋๋๋ค. IZMS๋ ๋ฉ์ผ ํ์ผ๋ช ์ด ์ค๋ณต๋์ด๋ ๊ฒฝ๊ณ ๋ ์๋ฌ ๋ฉ์์ง๋ฅผ ๋์ฐ์ง ์์ต๋๋ค.
IZMS ์คํ์ ์ํด์ config.json
ํ์ผ์ด ์คํํ์ผ๊ณผ ๊ฐ์ ์์น์ ์์ด์ผ ํฉ๋๋ค.
config.json
ํ์ผ ์์ ์ ํตํด ๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก, HTML์ ์ด๋ฏธ์ง ํฌํจ ์ฌ๋ถ ๋ฑ์ ์ปค์คํฐ๋ง์ด์ง ํ ์ ์์ต๋๋ค.
์ค๋ช
์ ์ํด ์๋ ๋ฉ์ผ์ ์์๋ก ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
๋ฉ์ผID : m21937
๋ฉค๋ฒ์ด๋ฆ : ๋ฏธ์ผ์ํค ์ฌ์ฟ ๋ผ
๋ฉค๋ฒID : 2
์์ ์ผ์ : 2021/03/22 10:46
์ ๋ชฉ : ๐ฅบ๐๐ธ
๋ค์์ mail_path
๊ฐ์ ๋ณ๊ฒฝํ์ฌ ๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก๋ฅผ ์ปค์คํฐ๋ง์ด์งํ๋ ๋ช ๊ฐ์ง ์์๋ฅผ ๋ณด์ฌ์ค๋๋ค.
๋ฉค๋ฒID๋ก ํด๋ ๋ถ๋ฅ, ๋ฉ์ผID๋ก ์ ์ฅ (๊ธฐ๋ณธ๊ฐ)
{
"mail_path": "/mail/{member_id}/{mail_id}.html"
}
// ์ค์ ๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก : incoming/mail/2/m21937.html
๋ฉค๋ฒID๊ฐ ์๋ ๋ฉค๋ฒ์ด๋ฆ ํด๋์ ์ ์ฅ
{
"mail_path": "/mail/{member_name}/{mail_id}.html"
}
// ์ค์ ๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก : incoming/mail/๋ฏธ์ผ์ํค ์ฌ์ฟ ๋ผ/m21937.html
๋ชจ๋ ๋ฉ์ผ์ ํ ํด๋์ ์ ์ฅ
{
"mail_path": "/mail/{mail_id}.html"
}
// ์ค์ ๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก : incoming/mail/m21937.html
๋ฉ์ผ ์์ ์ผ๋ก ๋ถ๋ฅ, ๋ฉ์ผ ์ ๋ชฉ์ ํ์ผ๋ช ์ผ๋ก ์ฌ์ฉ
{
"mail_path": "/mail/{received:%Y%m%d}/{mail_id}_{subject}.html"
}
// ์ค์ ๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก : incoming/mail/20210322/m21937_๐ฅบ๐๐ธ.html
โ ๏ธ ๋ฉ์ผ ์ ๋ชฉ์ ์ด๋ชจ์ง๊ฐ ํฌํจ๋์ด ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ด์์ฒด์ ๋ ์ด๋ชจ์ง๊ฐ ๋ค์ด๊ฐ ํ์ผ๋ช ์ ์ ๋๋ก ํธ๋ค๋งํ์ง ๋ชป ํ ์ ์์ผ๋ ๋ฉ์ผ ์ ๋ชฉ์ ํ์ผ๋ช ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๊ทธ๋ค์ง ์ถ์ฒํ์ง ์์ต๋๋ค. ๋ํ, ํ์ผ๋ช ์ ํญ์mail_id
๋ฅผ ํฌํจ์ํค๋ ๊ฒ์ ์ถ์ฒํฉ๋๋ค.mail_id
๋ง์ด ๋ฉ์ผ์ ์ ์ผํ๊ฒ ๊ตฌ๋ถํ ์ ์๋ ์๋จ์ ๋๋ค.
๋ฉ์ผ ์์ ์ผ๋ก ๋ถ๋ฅ, ๋ฉค๋ฒ์ด๋ฆ๊ณผ ๋ฉ์ผ ์ ๋ชฉ์ ํ์ผ๋ช ์ผ๋ก ์ฌ์ฉ
{
"mail_path": "/mail/{received:%Y%m%d}/{mail_id}_{member_name}_{subject}.html"
}
// ์ค์ ๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก : incoming/mail/20210322/m21937_๋ฏธ์ผ์ํค ์ฌ์ฟ ๋ผ_๐ฅบ๐๐ธ.html
์ด๋ฏธ์ง์ CSS๋ฅผ ๋ณ๋ ๊ฒฝ๋ก์ ์ ์ฅ (๊ธฐ๋ณธ๊ฐ)
{
"profile_image_path": "/",
"css_path": "/css",
"image_path": "/img"
}
// ํ๋กํ ์ด๋ฏธ์ง ์ ์ฅ ๊ฒฝ๋ก : incoming/ (์๋ ์๋ฒ์ path ๊ตฌ์กฐ๋ฅผ ๊ทธ๋๋ก ์ ์ฅ)
// CSS ์ ์ฅ ๊ฒฝ๋ก : incoming/css/
// ์ด๋ฏธ์ง ์ ์ฅ ๊ฒฝ๋ก : incoming/img/
์ด๋ฏธ์ง์ CSS๋ฅผ HTML ์์ ํฌํจ์ํค๊ธฐ
{
"profile_image_path": null,
"css_path": null,
"image_path": null
}
์ด ๊ฒฝ์ฐ ๋ชจ๋ ์ ๋ณด๊ฐ HTML ํ์ผ ์์ ํฌํจ๋๋ฏ๋ก ๋์ค์ HTML ํ์ผ ์์น๋ฅผ ๋ฐ๊ฟ๋ ๋ ์ด์์์ด๋ ์ด๋ฏธ์ง๊ฐ ๊นจ์ง์ง ์๋ ์ฅ์ ์ด ์์ต๋๋ค.
CSS๋ HTML์ <style>
ํ๊ทธ ์์, ์ด๋ฏธ์ง๋ base64๋ก ์ธ์ฝ๋ฉ๋์ด ๋ด์ฅ๋ฉ๋๋ค.
์ฒซ ์คํ์ ์์ฑ๋๋ ๋ฉํ๋ฐ์ดํฐ ํ์ผ๋ก์จ ๋ก์ปฌ์ ๋ค์ด๋ก๋ํ ๋ฉ์ผ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ต๋๋ค. ๋ง์ฝ ์ค์ ํ์ผ ๋ณ๊ฒฝ ๋ฑ์ ์ด์ ๋ก ๋ฐฑ์ ์ ์ฒ์๋ถํฐ ๋ค์ ํ๊ณ ์ ํ๋ ๊ฒฝ์ฐ ๋ค์ด๋ก๋ ํด๋์ ์ด ๋ ํ์ผ์ ์ญ์ ํ์๊ธฐ ๋ฐ๋๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ค์ ํ์ผ์ ๋๋ค. ์คํํ์ผ๊ณผ ๊ฐ์ ํด๋์ ์์นํด์ผํฉ๋๋ค. ์ ํจํ key๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ฐฑ์ ํ ๋ฉ์ผ์ฑ์ bundle id์ ๋๋ค. ์ด ๊ฐ์ ๋ฐ๋ผ ์์ฒญํ๋ API endpoint, CSS ๋ฑ์ด ๊ฒฐ์ ๋ฉ๋๋ค.
- com.ca-smart.izonemail
- com.camobile.hkt48mail
๋ฉ์ผ๊ณผ ๊ธฐํ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋ ๋ฃจํธ ๋๋ ํ ๋ฆฌ์ ๋๋ค.
๋ฉ์ผ ์ ์ฅ ๊ฒฝ๋ก ํ ํ๋ฆฟ์ ๋๋ค. ๋ค์๊ณผ ๊ฐ์ ์นํ๊ฐ๋ฅํ ๋ณ์๋ค์ด ์์ต๋๋ค.
{member_id}
: ๋ฉค๋ฒ ID (str
){member_name}
: ๋ฉค๋ฒ ์ด๋ฆ (str
){mail_id}
: ๋ฉ์ผ ID (str
){received}
: ๋ฉ์ผ ์์ ์ผ์ (datetime
){subject}
: ๋ฉ์ผ ์ ๋ชฉ (str
)
ํ๋กํ ์ฌ์ง์ด ์ ์ฅ๋ ์ ๋๊ฒฝ๋ก๋ฅผ ์ง์ ํฉ๋๋ค. ๊ธฐ์กด ์๋ฒ์ path๋ฅผ ๊ทธ๋๋ก ์ ์งํฉ๋๋ค.
๋ง์ฝ ์ด ๊ฐ์ด null
์ธ ๊ฒฝ์ฐ ํ๋กํ ์ฌ์ง์ base64 ์ธ์ฝ๋ฉ๋์ด HTML์ ๋ด์ฅ๋ฉ๋๋ค.
CSS๊ฐ ์ ์ฅ๋ ์ ๋๊ฒฝ๋ก๋ฅผ ์ง์ ํฉ๋๋ค. ๋ง์ฝ ์ด ๊ฐ์ด null
์ธ ๊ฒฝ์ฐ CSS๋ HTML์ ๋ด์ฅ๋ฉ๋๋ค.
๋ฉ์ผ ๋ณธ๋ฌธ์ ์ฌ์ง์ด ์ ์ฅ๋ ์ ๋๊ฒฝ๋ก๋ฅผ ์ง์ ํฉ๋๋ค. ์ค์ ์ ์ฅ ์์น๋ ์ค์ ์๋ฒ์ path์์ ๋งจ ๋์ 3๊ฐ ๊ฒฝ๋ก๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
๋๋ถ๋ถ์ ๊ฒฝ์ฐ /img/{๋ฉค๋ฒID}/{๋ฉ์ผ๋ฐ์ ์ผYYYYMMDD}/{ํ์ผ๋ช
}
์ ํํ๋ฅผ ๊ฐ์ง๋๋ค.
REST API ์์ฒญ์ ์ฌ์ฉ๋๋ ํค๋๋ฅผ ์ ์ํฉ๋๋ค. key๋ ๋ชจ๋ ์๋ฌธ์์ ๋๋ค.
-
user-id
: ์ ์ ID -
access-token
: ์ก์ธ์ค ํ ํฐ -
terms-version
: ์ฝ๊ด ๋์ ๋ฒ์ ("5") -
os-type
: ๋ชจ๋ฐ์ผ ์ด์์ฒด์ ํ์ ["iOS", "android"] -
application-version
: ํ๋ฉ์ฑ ๋ฒ์ iOS: "1.2.3", android: "1.4.5" (์์ฑ์ผ(2021.03.22) ๊ธฐ์ค) -
application-language
: ์ฑ ์ธ์ด ["ko", "ja", "en"] (๋ฉค๋ฒ ์ด๋ฆ ์ธ์ด๋ฅผ ๋ฐ๊ฟ ์ ์์) -
๊ธฐํ optional header:
device-version
,os-version
-
๊ธฐํ HTTP header:
user-agent
,accept-encoding
,accept
,accept-language
HTTP ์์ฒญ timeout (์ด)
HTTP ์์ฒญ ์คํจ์ ์ต๋ ์ฌ์๋ ํ์
HTTP ์์ฒญ๊ณผ ์ ์ฅ์ ์ํํ๋ ์ค๋ ๋ ๊ฐ์
๊ฐ์ฅ ์ต๊ทผ์ ๋ฐ์ ๋ฉ์ผ์ ์ผ์๋ฅผ ์ ์ฅํ๋ ๋ฉํ๋ฐ์ดํฐ ํ์ผ๋ช ์ ์ง์ ํฉ๋๋ค.
์ฑ๊ณต์ ์ผ๋ก ๋ค์ด๋ก๋ ๋ฐ์ ๋ฉ์ผ์ id๋ฅผ ์ ์ฅํ๋ ๋ฉํ๋ฐ์ดํฐ ํ์ผ๋ช ์ ์ง์ ํฉ๋๋ค.
ํ๋ก๊ทธ๋จ ์ข ๋ฃ์ ํธ์ถ๋ ํธ๋ค๋ฌ ๊ฒฝ๋ก (args: "program name" "num of downloaded mails")