├── hosting
└── src
│ ├── static
│ ├── .gitkeep
│ ├── favicon.ico
│ ├── apple-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-96x96.png
│ ├── ms-icon-70x70.png
│ ├── apple-icon-57x57.png
│ ├── apple-icon-60x60.png
│ ├── apple-icon-72x72.png
│ ├── apple-icon-76x76.png
│ ├── favicon-opengraph.png
│ ├── ms-icon-144x144.png
│ ├── ms-icon-150x150.png
│ ├── ms-icon-310x310.png
│ ├── android-icon-36x36.png
│ ├── android-icon-48x48.png
│ ├── android-icon-72x72.png
│ ├── android-icon-96x96.png
│ ├── apple-icon-114x114.png
│ ├── apple-icon-120x120.png
│ ├── apple-icon-144x144.png
│ ├── apple-icon-152x152.png
│ ├── apple-icon-180x180.png
│ ├── android-icon-144x144.png
│ ├── android-icon-192x192.png
│ ├── apple-icon-precomposed.png
│ ├── politica-de-privacidade-v1.pdf
│ ├── browserconfig.xml
│ └── manifest.json
│ ├── ads.txt
│ ├── robots.txt
│ ├── config
│ ├── prod.env.js
│ ├── dev.env.js
│ ├── app.sample.js
│ └── index.js
│ ├── build
│ ├── logo.png
│ ├── vue-loader.conf.js
│ ├── build.js
│ ├── check-versions.js
│ ├── webpack.base.conf.js
│ ├── utils.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
│ ├── src
│ ├── assets
│ │ ├── logo.png
│ │ ├── tmau1.png
│ │ ├── tmau2.png
│ │ ├── tmau3.png
│ │ ├── chevron-left.svg
│ │ ├── bear.svg
│ │ └── bear2.svg
│ ├── store
│ │ ├── getters.js
│ │ ├── actions.js
│ │ ├── index.js
│ │ └── mutations.js
│ ├── main.js
│ ├── utils.js
│ ├── router
│ │ └── index.js
│ ├── scss
│ │ └── _color.scss
│ ├── App.vue
│ └── components
│ │ ├── messageDetail.vue
│ │ ├── global
│ │ ├── GlobalHeader.vue
│ │ ├── bear.vue
│ │ ├── GlobalBear.vue
│ │ ├── GlobalFooter.vue
│ │ └── GlobalEmailForm.vue
│ │ ├── messageList.vue
│ │ └── createEmail.vue
│ ├── .editorconfig
│ ├── .gitignore
│ ├── .postcssrc.js
│ ├── .babelrc
│ ├── README.md
│ ├── package.json
│ └── index.html
├── functions
├── .gitignore
├── config
│ └── app.sample.js
├── index.js
├── package.json
├── src
│ ├── mailgun.js
│ └── sendgrid.js
└── utils.js
├── database.rules.json
├── README.md
├── firebase.json
├── LICENSE
└── .gitignore
/hosting/src/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/functions/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/hosting/src/ads.txt:
--------------------------------------------------------------------------------
1 | google.com, pub-3468723296547492, DIRECT, f08c47fec0942fa0
2 |
--------------------------------------------------------------------------------
/hosting/src/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Allow: /static/
3 | Allow: /
4 | Disallow: /*
5 |
--------------------------------------------------------------------------------
/hosting/src/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/hosting/src/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/build/logo.png
--------------------------------------------------------------------------------
/hosting/src/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/favicon.ico
--------------------------------------------------------------------------------
/hosting/src/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/src/assets/logo.png
--------------------------------------------------------------------------------
/hosting/src/src/assets/tmau1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/src/assets/tmau1.png
--------------------------------------------------------------------------------
/hosting/src/src/assets/tmau2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/src/assets/tmau2.png
--------------------------------------------------------------------------------
/hosting/src/src/assets/tmau3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/src/assets/tmau3.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon.png
--------------------------------------------------------------------------------
/hosting/src/static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/favicon-16x16.png
--------------------------------------------------------------------------------
/hosting/src/static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/favicon-32x32.png
--------------------------------------------------------------------------------
/hosting/src/static/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/favicon-96x96.png
--------------------------------------------------------------------------------
/hosting/src/static/ms-icon-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/ms-icon-70x70.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-57x57.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-60x60.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-72x72.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-76x76.png
--------------------------------------------------------------------------------
/hosting/src/static/favicon-opengraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/favicon-opengraph.png
--------------------------------------------------------------------------------
/hosting/src/static/ms-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/ms-icon-144x144.png
--------------------------------------------------------------------------------
/hosting/src/static/ms-icon-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/ms-icon-150x150.png
--------------------------------------------------------------------------------
/hosting/src/static/ms-icon-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/ms-icon-310x310.png
--------------------------------------------------------------------------------
/hosting/src/static/android-icon-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/android-icon-36x36.png
--------------------------------------------------------------------------------
/hosting/src/static/android-icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/android-icon-48x48.png
--------------------------------------------------------------------------------
/hosting/src/static/android-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/android-icon-72x72.png
--------------------------------------------------------------------------------
/hosting/src/static/android-icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/android-icon-96x96.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-114x114.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-120x120.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-144x144.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-152x152.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-180x180.png
--------------------------------------------------------------------------------
/hosting/src/static/android-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/android-icon-144x144.png
--------------------------------------------------------------------------------
/hosting/src/static/android-icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/android-icon-192x192.png
--------------------------------------------------------------------------------
/hosting/src/static/apple-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/apple-icon-precomposed.png
--------------------------------------------------------------------------------
/hosting/src/static/politica-de-privacidade-v1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edtsz/tuamaeaquelaursa/HEAD/hosting/src/static/politica-de-privacidade-v1.pdf
--------------------------------------------------------------------------------
/hosting/src/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/hosting/src/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/functions/config/app.sample.js:
--------------------------------------------------------------------------------
1 | // use https://firebase.google.com/docs/functions/config-env instead
2 |
3 | exports.token = 'your_custom_token';
4 | exports.remove_older_than = 86400000; // milliseconds
5 |
6 |
--------------------------------------------------------------------------------
/hosting/src/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 | .tool-versions
16 |
--------------------------------------------------------------------------------
/hosting/src/config/app.sample.js:
--------------------------------------------------------------------------------
1 | export const hostingConfig = {
2 | suffix: '@${your_domain}'
3 | };
4 |
5 | export const firebaseConfig = {
6 | apiKey: "{apiKey}",
7 | authDomain: "{authDomain}",
8 | databaseURL: "{databaseURL}",
9 | };
10 |
--------------------------------------------------------------------------------
/functions/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const utils = require('./utils.js');
4 | const glob = require('glob');
5 |
6 | const files = glob.sync('./src/*.js', { cwd: __dirname });
7 |
8 | files.forEach(file => {
9 | require(file)(exports, utils);
10 | })
11 |
--------------------------------------------------------------------------------
/database.rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "INBOX": {
4 | "$user_hash": {
5 | ".read": true,
6 | ".write": false
7 | }
8 | },
9 | "INDEX": {
10 | "$uid" : {
11 | ".read": true
12 | }
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://tuamaeaquelaursa.com)
2 |
3 | # Emails descartáveis @tuamaeaquelaursa.com
4 |
5 | [Tua mãe, aquela ursa](https://tuamaeaquelaursa.com) é o email descartável que você precisa pra zoar a equipe de marketing que fica enviando SPAM
6 |
--------------------------------------------------------------------------------
/hosting/src/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/hosting/src/static/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 | #ffffff
--------------------------------------------------------------------------------
/hosting/src/src/store/getters.js:
--------------------------------------------------------------------------------
1 |
2 | export const messages = state => {
3 | return state.messages;
4 | }
5 |
6 | export const message = state => {
7 | return state.messages.find((currentValue, index, arr) => {
8 | return currentValue.key == state.current_params.message;
9 | }) || state.notFound;
10 | }
11 |
--------------------------------------------------------------------------------
/hosting/src/src/assets/chevron-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/hosting/src/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "env",
5 | {
6 | "modules": false,
7 | "targets": {
8 | "browsers": [
9 | "> 1%",
10 | "last 2 versions",
11 | "not ie <= 8"
12 | ]
13 | }
14 | }
15 | ],
16 | "stage-2"
17 | ],
18 | "plugins": [
19 | "transform-vue-jsx",
20 | "transform-runtime"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/hosting/src/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue';
4 | import App from '@/App';
5 | import store from '@/store';
6 | import router from '@/router';
7 |
8 | Vue.config.productionTip = false;
9 |
10 | new Vue({
11 | el: '#app',
12 | store,
13 | router,
14 | render: h => h(App)
15 | })
16 |
--------------------------------------------------------------------------------
/hosting/src/README.md:
--------------------------------------------------------------------------------
1 | # tuamaeaquelaursa.com
2 |
3 | > Crie um email descartável @tuamaeaquelaursa.com
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 |
17 | # build for production and view the bundle analyzer report
18 | npm run build --report
19 | ```
20 |
21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
22 |
--------------------------------------------------------------------------------
/hosting/src/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/functions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "functions",
3 | "description": "Tua mãe, aquela ursa | API",
4 | "scripts": {
5 | "serve": "firebase serve --only functions",
6 | "shell": "firebase functions:shell",
7 | "start": "npm run shell",
8 | "deploy": "firebase deploy --only functions",
9 | "logs": "firebase functions:log"
10 | },
11 | "engines": {
12 | "node": "12"
13 | },
14 | "dependencies": {
15 | "busboy": "^0.3.1",
16 | "firebase-admin": "^8.13.0",
17 | "firebase-functions": "^3.22.0",
18 | "glob": "^7.2.3"
19 | },
20 | "devDependencies": {
21 | "firebase-functions-test": "^0.1.6"
22 | },
23 | "private": true
24 | }
25 |
--------------------------------------------------------------------------------
/hosting/src/src/utils.js:
--------------------------------------------------------------------------------
1 | export const fancy_date = ( date ) => {
2 | let cur_date = new Date();
3 | let msg_date = new Date( date * 1000 );
4 | let options = {
5 | hour: 'numeric',
6 | minute: 'numeric'
7 | };
8 |
9 | if ( msg_date.getMonth() < cur_date.getMonth() ) {
10 | options.weekday = 'short';
11 | options.month = 'short';
12 | options.day = '2-digit';
13 | } else {
14 | if ( msg_date.getDate() < cur_date.getDate() ) {
15 | options.weekday = 'short';
16 | options.day = '2-digit';
17 | }
18 |
19 | if ( msg_date.getDate() == cur_date.getDate() )
20 | options.second = 'numeric';
21 | }
22 |
23 | return msg_date.toLocaleString(navigator.language, options);
24 | }
25 |
--------------------------------------------------------------------------------
/functions/src/mailgun.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const functions = require('firebase-functions');
4 |
5 |
6 | module.exports = function (e, utils) {
7 | e.mailgun = functions.https.onRequest((request, response, next) => {
8 | if ( !utils.isValidRequest(request) )
9 | return response.status(401).send();
10 |
11 | const fields = {
12 | from : request.body['from'] || null,
13 | recipient : request.body['recipient'] || null,
14 | subject : request.body['subject'] || null,
15 | bodyHtml : request.body['body-html'] || null,
16 | bodyPlain : request.body['body-plain'] || null,
17 | headers : request.body['headers'] || null,
18 | };
19 |
20 | response.send(utils.addNewMessage(fields));
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "database": {
3 | "rules": "database.rules.json"
4 | },
5 | "hosting": {
6 | "public": "hosting/public",
7 | "ignore": [
8 | "firebase.json",
9 | "**/.*",
10 | "**/node_modules/**"
11 | ],
12 | "rewrites": [
13 | {
14 | "source": "**",
15 | "destination": "/index.html"
16 | }
17 | ],
18 | "headers": [{
19 | "source": "**/*",
20 | "headers": [
21 | {"key": "X-Frame-Options", "value": "DENY"},
22 | {"key": "X-Content-Type-Options", "value": "nosniff"},
23 | {"key": "X-UA-Compatible", "value": "ie=edge"},
24 | {"key": "X-XSS-Protection", "value": "1; mode=block"}
25 | ]
26 | }]
27 | },
28 | "emulators": {
29 | "database": {
30 | "host": "0.0.0.0",
31 | "port": "9001"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/hosting/src/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 | import ga from 'vue-ga';
4 | import CreateEmail from '@/components/createEmail.vue';
5 | import MessageList from '@/components/messageList.vue';
6 | import MessageDetail from '@/components/messageDetail.vue';
7 |
8 | Vue.use(Router);
9 |
10 | const router = new Router({
11 | mode: 'history',
12 | routes: [
13 | {
14 | path: '/',
15 | name: 'Home',
16 | component: CreateEmail,
17 | },
18 | {
19 | path: '/:email',
20 | name: 'MessageList',
21 | component: MessageList,
22 | },
23 | {
24 | path: '/:email/:message',
25 | name: 'MessageDetail',
26 | component: MessageDetail,
27 | }
28 | ],
29 | scrollBehavior (to, from, savedPosition) {
30 | return { x: 0, y: 0 };
31 | }
32 | });
33 |
34 | ga(router, 'UA-126612006-1');
35 |
36 | export default router
37 |
--------------------------------------------------------------------------------
/hosting/src/src/scss/_color.scss:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------
2 | // Base Color
3 | //-----------------------------------------------
4 | $app-background: #859CC2;
5 | $app-foreground: #FFFFFF;
6 |
7 | //-----------------------------------------------
8 | // Text colors
9 | //-----------------------------------------------
10 | $bright-text: #FFFFFF;
11 | $dark-text: #040404;
12 |
13 | //-----------------------------------------------
14 | // CALL TO ACTION - colors
15 | //-----------------------------------------------
16 | $cta-base: #FF1B5F;
17 | $cta-base-text: #FFFFFF;
18 | $cta-hover: darken($cta-base, 10%);
19 | $cta-hover-text: #FFFFFF;
20 |
21 | // #DDE8F9
22 | // #C5B697
23 | // #383838
24 | // #775D46
25 |
26 | $background: #DDE8F9;
27 | $lighter-brown: #DAC4A5;
28 | $light-brown: #C5B697;
29 | $dark-brown: #765D46;
30 | $light-black: #464646;
31 | $black: #383838;
32 | $gray: #A2A2A2;
33 | $light-gray: #F2F2F2;
34 |
--------------------------------------------------------------------------------
/hosting/src/static/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Tua mãe, aquela ursa",
3 | "icons": [
4 | {
5 | "src": "\/static\/android-icon-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image\/png",
8 | "density": "0.75"
9 | },
10 | {
11 | "src": "\/static\/android-icon-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image\/png",
14 | "density": "1.0"
15 | },
16 | {
17 | "src": "\/static\/android-icon-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image\/png",
20 | "density": "1.5"
21 | },
22 | {
23 | "src": "\/static\/android-icon-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image\/png",
26 | "density": "2.0"
27 | },
28 | {
29 | "src": "\/static\/android-icon-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image\/png",
32 | "density": "3.0"
33 | },
34 | {
35 | "src": "\/static\/android-icon-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image\/png",
38 | "density": "4.0"
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/hosting/src/src/store/actions.js:
--------------------------------------------------------------------------------
1 |
2 | export const clear = ({ commit, state }) => {
3 | console.info( 'action: clear' );
4 |
5 | commit('clear');
6 | }
7 |
8 |
9 |
10 | export const connect_to_box = ({ commit, state }) => {
11 | console.info( 'action: connect_to_box' );
12 |
13 | if ( state._user_box === null )
14 | commit('connect_to_box');
15 | }
16 |
17 |
18 |
19 | export const hydrate_messages = ({ commit, state }, params) => {
20 | console.info( 'action: hydrate_messages' );
21 |
22 | if ( state._user_box === null )
23 | throw 'user_box undefined.';
24 |
25 | if ( state.messages.length !== 0 ) {
26 | console.error('hydrate_messages: messages.length !== 0');
27 | return;
28 | }
29 |
30 | state._unsubscribe = state._user_box
31 | .onSnapshot((querySnapshot) => {
32 |
33 | querySnapshot.docChanges().forEach((change) => {
34 | var res = change.doc.data();
35 | res.key = change.doc.id;
36 |
37 | commit(`${change.type}_messages`, res);
38 | });
39 |
40 | commit('sort_messages');
41 | });
42 | }
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Uilicious Private Limited.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/functions/src/sendgrid.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const functions = require('firebase-functions');
4 | const Busboy = require('busboy');
5 |
6 | module.exports = function (e, utils) {
7 | e.sendgrid = functions.https.onRequest((request, response, next) => {
8 | if ( !utils.isValidRequest(request) )
9 | return response.status(401).send();
10 |
11 | const busboy = new Busboy({headers: request.headers});
12 | const input = {};
13 |
14 | busboy.on('field', (fieldname, val) => {
15 | input[fieldname] = val;
16 | });
17 |
18 | busboy.on('finish', () => {
19 |
20 | const fields = {
21 | from : input['from'] || null,
22 | recipient : input['to'] || null,
23 | subject : input['subject'] || null,
24 | bodyHtml : input['html'] || null,
25 | bodyPlain : input['text'] || null,
26 | headers : input['headers'] || null,
27 | };
28 |
29 | response.send(utils.addNewMessage(fields));
30 | });
31 |
32 | busboy.end(request.rawBody);
33 | });
34 | };
35 |
--------------------------------------------------------------------------------
/hosting/src/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
23 |
24 |
50 |
--------------------------------------------------------------------------------
/hosting/src/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/functions/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const functions = require('firebase-functions');
4 | const admin = require('firebase-admin');
5 |
6 | admin.initializeApp();
7 | const database = admin.firestore();
8 | const mailboxes = database.collection('MAILBOXES');
9 | const CONFIG = functions.config().app;
10 |
11 |
12 |
13 | const isValidRequest = (request) => CONFIG.token == request.query.token;
14 |
15 |
16 |
17 | const addNewMessage = (fields) => {
18 | if (! fields.recipient)
19 | return;
20 |
21 | const recipient = fields.recipient.match(/([\w-\.]+)@((?:[\w]+\.)+)([a-z]{2,4})/gi).shift().toLowerCase();
22 |
23 | const domain = recipient.split('@').pop();
24 | if (domain != 'tuamaeaquelaursa.com') {
25 | return {"message": "mailbox not found"};
26 | }
27 |
28 | var expires_at = new Date();
29 |
30 | if (recipient == 'falecom@tuamaeaquelaursa.com') {
31 | expires_at.setMonth(expires_at.getMonth() + 2);
32 | }
33 |
34 | const message = mailboxes.doc(recipient).collection('INBOX').add({
35 | recipient : recipient == 'falecom@tuamaeaquelaursa.com' ? recipient : 'any',
36 | from : fields.from,
37 | subject : fields.subject,
38 | bodyHtml : fields.bodyHtml,
39 | created_at : Date.now(),
40 | expires_at : admin.firestore.Timestamp.fromDate(expires_at),
41 | });
42 |
43 | return message;
44 | }
45 |
46 |
47 | module.exports = {
48 | isValidRequest,
49 | addNewMessage,
50 | }
51 |
--------------------------------------------------------------------------------
/hosting/src/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | firebase-debug.log*
8 |
9 | # Firebase cache
10 | .firebase/
11 |
12 | # Firebase config
13 |
14 | # Uncomment this if you'd like others to create their own Firebase project.
15 | # For a team working on the same Firebase project(s), it is recommended to leave
16 | # it commented so all members can deploy to the same project(s) in .firebaserc.
17 | .firebaserc
18 |
19 | # Runtime data
20 | pids
21 | *.pid
22 | *.seed
23 | *.pid.lock
24 |
25 | # Directory for instrumented libs generated by jscoverage/JSCover
26 | lib-cov
27 |
28 | # Coverage directory used by tools like istanbul
29 | coverage
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (http://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | package-lock.json
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Optional REPL history
57 | .node_repl_history
58 |
59 | # Output of 'npm pack'
60 | *.tgz
61 |
62 | # Yarn Integrity file
63 | .yarn-integrity
64 |
65 | # dotenv environment variables file
66 | .env
67 |
68 | # dist folder
69 | hosting/public/
70 |
71 | hosting/src/config/app.js
72 | functions/config/app.js
73 | .idea/
74 |
--------------------------------------------------------------------------------
/hosting/src/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 |
4 | import * as getters from './getters'
5 | import * as actions from './actions'
6 | import * as mutations from './mutations'
7 |
8 | import firebase from 'firebase/compat/app';
9 | import 'firebase/compat/firestore';
10 |
11 |
12 | import { hostingConfig, firebaseConfig } from '@/../config/app.js';
13 | import router from '@/router';
14 |
15 | Vue.use(Vuex);
16 |
17 | const state = {
18 | notFound: {
19 | from: 'Tua mãe, aquela ursa',
20 | subject: 'Correspondências não encontrada',
21 | bodyHtml: '
nada para exibir ¯\\_(ツ)_/¯',
22 | created_at: Date.now(),
23 | },
24 | loading: {
25 | from: 'Tua mãe, aquela ursa',
26 | subject: 'Buscando correspondências',
27 | bodyHtml: '... ',
28 | created_at: Date.now(),
29 | },
30 | messages: [],
31 | message: {},
32 | current_page: null,
33 | current_params: null,
34 | loader : false,
35 | _hosting : hostingConfig,
36 | _user_box: null,
37 | _unsubscribe: null,
38 | _db : firebase.initializeApp(firebaseConfig).firestore(),
39 | }
40 |
41 | state.message = state.loading;
42 |
43 | const store = new Vuex.Store({
44 | state,
45 | getters,
46 | actions,
47 | mutations
48 | });
49 |
50 |
51 | router.beforeEach((to, from, next) => {
52 | store.commit('current_page', to);
53 |
54 | if ( to.path === '/' )
55 | store.dispatch('clear');
56 | else
57 | store.dispatch('connect_to_box');
58 |
59 | next();
60 | });
61 |
62 | export default store
63 |
--------------------------------------------------------------------------------
/hosting/src/src/store/mutations.js:
--------------------------------------------------------------------------------
1 |
2 | export const current_page = (state, to) => {
3 | state.current_page = to.name;
4 | state.current_params = to.params;
5 |
6 | console.info('mutation: current_page = ' + to.name);
7 | }
8 |
9 |
10 | export const toggle_loader = (state) => {
11 | state.loader = !state.loader;
12 |
13 | console.info('mutation: toggle_loader = ' + state.loader);
14 | }
15 |
16 |
17 | export const clear = (state) => {
18 | state._unsubscribe && state._unsubscribe();
19 | state.messages = [];
20 | state.message = state.loading;
21 | state._user_box = null;
22 |
23 | console.info('mutation: cleared');
24 | }
25 |
26 |
27 | export const connect_to_box = (state) => {
28 | var recipient = (state.current_params.email + state._hosting.suffix).toLowerCase();
29 |
30 | state._user_box = state._db.collection('MAILBOXES').doc(recipient).collection('INBOX');
31 |
32 | console.info('mutation: connect_to_box');
33 | }
34 |
35 |
36 | export const added_messages = (state, msg) => {
37 | state.messages.unshift(msg);
38 |
39 | console.info('mutation: added_messages');
40 | }
41 |
42 |
43 | export const modified_messages = (state, msg) => {
44 | state.messages.forEach((currentValue, index, arr) => {
45 | if (currentValue.key === msg.key) {
46 | Object.keys(currentValue).forEach(prop => {
47 | if (msg[prop]) {
48 | currentValue[prop] = msg[prop];
49 | }
50 | })
51 | }
52 | });
53 |
54 | console.info('mutation: modified_messages');
55 | }
56 |
57 |
58 | export const removed_messages = (state, msg) => {
59 | state.messages.forEach((currentValue, index, arr) => { currentValue.key === msg.key && arr.splice(index, 1) });
60 |
61 | console.info('mutation: removed_messages ' + msg.key);
62 | }
63 |
64 |
65 | export const sort_messages = (state) => {
66 | console.log('sort');
67 |
68 | state.messages.sort((a, b) => {
69 | console.log('sorting');
70 | return a.created_at < b.created_at;
71 | })
72 |
73 | console.info('mutation: sort_messages ');
74 | }
75 |
--------------------------------------------------------------------------------
/hosting/src/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: '0.0.0.0', // can be overwritten by process.env.HOST
17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 |
24 | /**
25 | * Source Maps
26 | */
27 |
28 | // https://webpack.js.org/configuration/devtool/#development
29 | devtool: 'cheap-module-eval-source-map',
30 |
31 | // If you have problems debugging vue-files in devtools,
32 | // set this to false - it *may* help
33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
34 | cacheBusting: true,
35 |
36 | cssSourceMap: true
37 | },
38 |
39 | build: {
40 | // Template for index.html
41 | index: path.resolve(__dirname, '../../public/index.html'),
42 |
43 | // Paths
44 | assetsRoot: path.resolve(__dirname, '../../public'),
45 | assetsSubDirectory: 'static',
46 | assetsPublicPath: '/',
47 |
48 | /**
49 | * Source Maps
50 | */
51 |
52 | productionSourceMap: false,
53 | // https://webpack.js.org/configuration/devtool/#production
54 | devtool: '#source-map',
55 |
56 | // Gzip off by default as many popular static hosts such as
57 | // Surge or Netlify already gzip all static assets for you.
58 | // Before setting to `true`, make sure to:
59 | // npm install --save-dev compression-webpack-plugin
60 | productionGzip: false,
61 | productionGzipExtensions: ['js', 'css'],
62 |
63 | // Run the build command with an extra argument to
64 | // View the bundle analyzer report after build finishes:
65 | // `npm run build --report`
66 | // Set to `true` or `false` to always turn it on or off
67 | bundleAnalyzerReport: process.env.npm_config_report
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/hosting/src/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 |
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, '../'),
15 | entry: {
16 | app: './src/main.js'
17 | },
18 | output: {
19 | path: config.build.assetsRoot,
20 | filename: '[name].js',
21 | publicPath: process.env.NODE_ENV === 'production'
22 | ? config.build.assetsPublicPath
23 | : config.dev.assetsPublicPath
24 | },
25 | resolve: {
26 | extensions: ['.js', '.vue', '.json'],
27 | alias: {
28 | 'vue$': 'vue/dist/vue.esm.js',
29 | '@': resolve('src'),
30 | }
31 | },
32 | module: {
33 | rules: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'vue-loader',
37 | options: vueLoaderConfig
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel-loader',
42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
43 | },
44 | {
45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
50 | }
51 | },
52 | {
53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
54 | loader: 'url-loader',
55 | options: {
56 | limit: 10000,
57 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
58 | }
59 | },
60 | {
61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
62 | loader: 'url-loader',
63 | options: {
64 | limit: 10000,
65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
66 | }
67 | }
68 | ]
69 | },
70 | node: {
71 | // prevent webpack from injecting useless setImmediate polyfill because Vue
72 | // source contains it (although only uses it if it's native).
73 | setImmediate: false,
74 | // prevent webpack from injecting mocks to Node native modules
75 | // that does not make sense for the client
76 | dgram: 'empty',
77 | fs: 'empty',
78 | net: 'empty',
79 | tls: 'empty',
80 | child_process: 'empty'
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/hosting/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tuamaeaquelaursa.com",
3 | "version": "1.0.0",
4 | "description": "Crie um email descartável @tuamaeaquelaursa.com",
5 | "author": "Éderson Tiago Szlachta ",
6 | "private": true,
7 | "scripts": {
8 | "firebase": "firebase",
9 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
10 | "start": "npm run dev",
11 | "build": "node build/build.js",
12 | "deploy": "npm run build && npm run deploy-only",
13 | "deploy-only": "firebase deploy --only hosting"
14 | },
15 | "dependencies": {
16 | "firebase": "9.6.1",
17 | "normalize.css": "^8.0.1",
18 | "vue": "^2.6.10",
19 | "vue-ga": "^1.1.0",
20 | "vue-router": "^3.1.2",
21 | "vuex": "^3.1.1"
22 | },
23 | "devDependencies": {
24 | "autoprefixer": "^7.1.2",
25 | "babel-core": "^6.26.3",
26 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
27 | "babel-loader": "^7.1.1",
28 | "babel-plugin-syntax-jsx": "^6.18.0",
29 | "babel-plugin-transform-runtime": "^6.23.0",
30 | "babel-plugin-transform-vue-jsx": "^3.7.0",
31 | "babel-preset-env": "^1.7.0",
32 | "babel-preset-stage-2": "^6.24.1",
33 | "chalk": "^2.4.2",
34 | "copy-webpack-plugin": "^4.0.1",
35 | "css-loader": "^3.2.0",
36 | "extract-text-webpack-plugin": "^3.0.2",
37 | "file-loader": "^1.1.4",
38 | "firebase-tools": "^8.20.0",
39 | "friendly-errors-webpack-plugin": "^1.7.0",
40 | "html-webpack-externals-plugin": "^3.8.0",
41 | "html-webpack-plugin": "^2.30.1",
42 | "node-notifier": "^5.4.1",
43 | "node-sass": "^4.12.0",
44 | "optimize-css-assets-webpack-plugin": "^3.2.0",
45 | "ora": "^1.2.0",
46 | "portfinder": "^1.0.21",
47 | "postcss-import": "^11.0.0",
48 | "postcss-loader": "^2.0.8",
49 | "postcss-url": "^7.2.1",
50 | "rimraf": "^2.6.3",
51 | "sass-loader": "^7.2.0",
52 | "semver": "^5.3.0",
53 | "shelljs": "^0.7.6",
54 | "uglifyjs-webpack-plugin": "^1.1.1",
55 | "url-loader": "^2.1.0",
56 | "vue-loader": "^13.3.0",
57 | "vue-style-loader": "^3.0.1",
58 | "vue-template-compiler": "^2.6.10",
59 | "webpack": "^3.6.0",
60 | "webpack-bundle-analyzer": "^3.4.1",
61 | "webpack-cdn-plugin": "^3.1.4",
62 | "webpack-dev-server": "^2.9.1",
63 | "webpack-merge": "^4.2.1"
64 | },
65 | "engines": {
66 | "node": ">= 6.0.0",
67 | "npm": ">= 3.0.0"
68 | },
69 | "browserslist": [
70 | "> 1%",
71 | "last 2 versions",
72 | "not ie <= 8"
73 | ]
74 | }
75 |
--------------------------------------------------------------------------------
/hosting/src/src/components/messageDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
53 |
54 |
97 |
--------------------------------------------------------------------------------
/hosting/src/src/components/global/GlobalHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
25 |
26 |
111 |
--------------------------------------------------------------------------------
/hosting/src/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader'
51 | })
52 | } else {
53 | return ['vue-style-loader'].concat(loaders)
54 | }
55 | }
56 |
57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58 | return {
59 | css: generateLoaders(),
60 | postcss: generateLoaders(),
61 | less: generateLoaders('less'),
62 | sass: generateLoaders('sass', { indentedSyntax: true }),
63 | scss: generateLoaders('sass'),
64 | stylus: generateLoaders('stylus'),
65 | styl: generateLoaders('stylus')
66 | }
67 | }
68 |
69 | // Generate loaders for standalone style files (outside of .vue)
70 | exports.styleLoaders = function (options) {
71 | const output = []
72 | const loaders = exports.cssLoaders(options)
73 |
74 | for (const extension in loaders) {
75 | const loader = loaders[extension]
76 | output.push({
77 | test: new RegExp('\\.' + extension + '$'),
78 | use: loader
79 | })
80 | }
81 |
82 | return output
83 | }
84 |
85 | exports.createNotifierCallback = () => {
86 | const notifier = require('node-notifier')
87 |
88 | return (severity, errors) => {
89 | if (severity !== 'error') return
90 |
91 | const error = errors[0]
92 | const filename = error.file && error.file.split('!').pop()
93 |
94 | notifier.notify({
95 | title: packageConfig.name,
96 | message: severity + ': ' + error.name,
97 | subtitle: filename || '',
98 | icon: path.join(__dirname, 'logo.png')
99 | })
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/hosting/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | Tua mãe, aquela ursa
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/hosting/src/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../ads.txt'),
64 | to: '.',
65 | ignore: ['.*']
66 | },
67 | {
68 | from: path.resolve(__dirname, '../static'),
69 | to: config.dev.assetsSubDirectory,
70 | ignore: ['.*']
71 | }
72 | ])
73 | ]
74 | })
75 |
76 | module.exports = new Promise((resolve, reject) => {
77 | portfinder.basePort = process.env.PORT || config.dev.port
78 | portfinder.getPort((err, port) => {
79 | if (err) {
80 | reject(err)
81 | } else {
82 | // publish the new Port, necessary for e2e tests
83 | process.env.PORT = port
84 | // add port to devServer config
85 | devWebpackConfig.devServer.port = port
86 |
87 | // Add FriendlyErrorsPlugin
88 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
89 | compilationSuccessInfo: {
90 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
91 | },
92 | onErrors: config.dev.notifyOnErrors
93 | ? utils.createNotifierCallback()
94 | : undefined
95 | }))
96 |
97 | resolve(devWebpackConfig)
98 | }
99 | })
100 | })
101 |
--------------------------------------------------------------------------------
/hosting/src/src/assets/bear.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/hosting/src/src/components/messageList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Tua mãe, aquela ursa foi buscar as correspondências para você.
5 |
6 |
7 |
8 |
9 | {{msg.from}}
10 | {{msg.subject}}
11 | {{fancy_date(msg.created_at)}}
12 |
13 |
14 |
15 |
Tua mãe, aquela ursa não encontrou tuas cartas. ¯\_(ツ)_/¯
16 |
17 |
18 |
19 |
20 |
21 |
65 |
66 |
140 |
--------------------------------------------------------------------------------
/hosting/src/src/components/global/bear.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
182 |
--------------------------------------------------------------------------------
/hosting/src/src/components/global/GlobalBear.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
20 |
21 |
191 |
--------------------------------------------------------------------------------
/hosting/src/src/components/global/GlobalFooter.vue:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
55 |
56 |
134 |
--------------------------------------------------------------------------------
/hosting/src/src/assets/bear2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | Em mãenutenção!
46 | Alguma coisa de errada não está certa
47 |
48 |
--------------------------------------------------------------------------------
/hosting/src/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin')
11 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
12 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
13 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
14 |
15 | const env = require('../config/prod.env')
16 |
17 | const webpackConfig = merge(baseWebpackConfig, {
18 | module: {
19 | rules: utils.styleLoaders({
20 | sourceMap: config.build.productionSourceMap,
21 | extract: true,
22 | usePostCSS: true
23 | })
24 | },
25 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
26 | output: {
27 | path: config.build.assetsRoot,
28 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
29 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
30 | },
31 | plugins: [
32 | new HtmlWebpackExternalsPlugin({
33 | externals: [
34 | {
35 | module: 'normalize.css',
36 | entry: 'https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css',
37 | global: 'normalize.css',
38 | },
39 | {
40 | module: 'core-js',
41 | entry: 'https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.9/core.min.js',
42 | global: 'core-js',
43 | },
44 | {
45 | module: 'underscore',
46 | entry: 'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js',
47 | global: 'underscore',
48 | },
49 | {
50 | module: 'lodash',
51 | entry: 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js',
52 | global: 'lodash',
53 | },
54 | {
55 | module: 'vue',
56 | entry: 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js',
57 | global: 'Vue',
58 | },
59 | {
60 | module: 'vue-router',
61 | entry: 'https://unpkg.com/vue-router@3.1.2/dist/vue-router.min.js',
62 | global: 'VueRouter',
63 | },
64 | {
65 | module: 'vuex',
66 | entry: 'https://unpkg.com/vuex@3.1.1/dist/vuex.min.js',
67 | global: 'Vuex',
68 | },
69 | ],
70 | }),
71 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
72 | new webpack.DefinePlugin({
73 | 'process.env': env
74 | }),
75 | new UglifyJsPlugin({
76 | uglifyOptions: {
77 | compress: {
78 | warnings: false
79 | }
80 | },
81 | sourceMap: config.build.productionSourceMap,
82 | parallel: true
83 | }),
84 | // extract css into its own file
85 | new ExtractTextPlugin({
86 | filename: utils.assetsPath('css/[name].[contenthash].css'),
87 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
88 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
89 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
90 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
91 | allChunks: true,
92 | }),
93 | // Compress extracted CSS. We are using this plugin so that possible
94 | // duplicated CSS from different components can be deduped.
95 | new OptimizeCSSPlugin({
96 | cssProcessorOptions: config.build.productionSourceMap
97 | ? { safe: true, map: { inline: false } }
98 | : { safe: true }
99 | }),
100 | // generate dist index.html with correct asset hash for caching.
101 | // you can customize output by editing /index.html
102 | // see https://github.com/ampedandwired/html-webpack-plugin
103 | new HtmlWebpackPlugin({
104 | filename: config.build.index,
105 | template: 'index.html',
106 | inject: true,
107 | minify: {
108 | removeComments: true,
109 | collapseWhitespace: true,
110 | removeAttributeQuotes: true
111 | // more options:
112 | // https://github.com/kangax/html-minifier#options-quick-reference
113 | },
114 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
115 | chunksSortMode: 'dependency'
116 | }),
117 | // keep module.id stable when vendor modules does not change
118 | new webpack.HashedModuleIdsPlugin(),
119 | // enable scope hoisting
120 | new webpack.optimize.ModuleConcatenationPlugin(),
121 | // split vendor js into its own file
122 | new webpack.optimize.CommonsChunkPlugin({
123 | name: 'vendor',
124 | minChunks (module) {
125 |
126 | if ( module.resource &&
127 | /\.js$/.test(module.resource) &&
128 | module.resource.indexOf(
129 | path.join(__dirname, '../node_modules')
130 | ) === 0 )
131 | console.log( module.resource )
132 |
133 | // any required modules inside node_modules are extracted to vendor
134 | return (
135 | module.resource &&
136 | /\.js$/.test(module.resource) &&
137 | module.resource.indexOf(
138 | path.join(__dirname, '../node_modules')
139 | ) === 0
140 | )
141 | }
142 | }),
143 | // extract webpack runtime and module manifest to its own file in order to
144 | // prevent vendor hash from being updated whenever app bundle is updated
145 | new webpack.optimize.CommonsChunkPlugin({
146 | name: 'manifest',
147 | minChunks: Infinity
148 | }),
149 | // This instance extracts shared chunks from code splitted chunks and bundles them
150 | // in a separate chunk, similar to the vendor chunk
151 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
152 | new webpack.optimize.CommonsChunkPlugin({
153 | name: 'app',
154 | async: 'vendor-async',
155 | children: true,
156 | minChunks: 3
157 | }),
158 |
159 | // copy custom static assets
160 | new CopyWebpackPlugin([
161 | {
162 | from: path.resolve(__dirname, '../ads.txt'),
163 | to: '.',
164 | ignore: ['.*']
165 | },
166 | {
167 | from: path.resolve(__dirname, '../static'),
168 | to: config.build.assetsSubDirectory,
169 | ignore: ['.*']
170 | }
171 | ])
172 | ]
173 | })
174 |
175 | if (config.build.productionGzip) {
176 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
177 |
178 | webpackConfig.plugins.push(
179 | new CompressionWebpackPlugin({
180 | asset: '[path].gz[query]',
181 | algorithm: 'gzip',
182 | test: new RegExp(
183 | '\\.(' +
184 | config.build.productionGzipExtensions.join('|') +
185 | ')$'
186 | ),
187 | threshold: 10240,
188 | minRatio: 0.8
189 | })
190 | )
191 | }
192 |
193 | if (config.build.bundleAnalyzerReport) {
194 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
195 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
196 | }
197 |
198 | module.exports = webpackConfig
199 |
--------------------------------------------------------------------------------
/hosting/src/src/components/createEmail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Como funciona
6 |
7 |
10 |
11 |
1. Tua mãe, aquela ursa recebe seus emails
12 |
Você poderá acessar todos os emails recebidos pelo seu email {{_hosting.suffix}}. Não é preciso criar o email antes, tua mãe, aquela ursa aceita tudo e filtra o que pertence ao seu endereço temporário
13 |
14 |
15 |
16 |
17 |
2. Acesse seu email {{_hosting.suffix.replace(/\.com.*/, '')}}
18 |
É só preencher o endereço no campo acima, ou você pode acessar diretamente pela URL https://{{_hosting.suffix.replace('@', '')}}/nome-do-seu-email
19 |
20 |
23 |
24 |
25 |
28 |
29 |
3. Destruimos tudo para você
30 |
Após algumas horas, todos os emails recebidos por Tua mãe, aquela ursa são destruídos, sem nenhum resquício. Assim ninguém ficará sabendo das coisas que Tua mãe, aquela ursa recebeu no passado
31 |
32 |
33 |
34 |
35 |
36 |
Por que?
37 |
38 |
39 |
40 |
Evite SPAM
41 |
Precisa se cadastrar em um site ou baixar um ebook que requer email? Evite SPAM, utilize um email descartável. Ele dura algumas horas e você poderá receber o email de confirmação de cadastro/link de download.
42 |
43 |
44 |
Irrite Marketeiros
45 |
Imagina só a reação do pessoal do marketing quando perceber que estão mandando emails para ”tua mãe, aquela ursa”. Bom, eles merecem, ninguém gosta de SPAM.
46 |
47 |
48 |
Emails autodestrutivos
49 |
Depois de algumas horas, o endereço de email e todos os emails que você recebeu vão pelos ares. Não se preocupe, utilizamos ingredientes orgânicos e todos os emails são reciclados.
50 |
51 |
52 |
53 |
54 |
55 |
Blog
56 |
57 |
58 |
59 |
60 |
Evite SPAM
61 |
Você já pensou em usar uma caixa de email temporária para proteger sua privacidade digital? Se você quer ter maior controle sobre o que é compartilhado e principalmente e com quem então uma caixa de email temporária é a solução certa para você!
62 |
Uma caixa de email temporária oferece uma série de vantagens, incluindo maior segurança, menor risco de violação de dados, sem comprometer a conta principal, sem SPAM e sem política de retenção de dados. Além disso, é muito fácil de usar e você pode criar uma conta em segundos.
63 |
Embora não seja uma prática adequada para todas as situações, ela pode ser útil se você precisar se registrar em um site ou serviço que exige um endereço de email válido. Assim, você pode usar o serviço sem expor sua conta principal.
64 |
Portanto, se você estiver à procura de uma maneira fácil e segura de proteger sua privacidade digital, considere o uso de uma caixa de email temporária. Ela é uma excelente solução para quem deseja ter maior controle sobre o que é compartilhado e principalmente com quem.
65 |
Uma outra prática muito comum são as criações de emails temporários para realização de testes em sistemas, permitindo assim criar cenários de inserção de novos usuários para aquele sistema e acompanhar uma jornada desde o inicio.
66 |
Além disso, é importante lembrar que a caixa de email temporária não deve ser usada para fins críticos, como o acesso a contas bancárias ou informações confidenciais. Isso porque, como o nome sugere, ela é temporária e não é projetada para uso a longo prazo.
67 |
É importante lembrar que, apesar de as caixas de email temporárias oferecerem proteção extra, elas não garantem a segurança total. Por isso, é importante que você tome medidas adicionais para garantir a segurança de suas informações pessoais, como o uso de senhas seguras e o compartilhamento de informações confidenciais somente com quem você confia. Por meio dessas medidas, você pode ter a certeza de que suas informações estão seguras online.
68 |
Mantenha o spam longe de seu e-mail e fique seguro, utilize um endereço de e-mail descartável anônimo! Proteja o seu endereço de e-mail pessoal de abusos online como spam, bots, phishing.
69 |
Fique protegido. Sempre.
70 |
71 |
72 |
73 |
Vazamentos de Dados: Um Risco Crescente
74 |
Os vazamentos de dados se tornaram uma preocupação crescente na era digital, com empresas e indivíduos cada vez mais vulneráveis a ataques cibernéticos. Esses incidentes não só expõem informações confidenciais, mas também afetam a confiança dos usuários nas organizações afetadas. Este artigo examinará os riscos associados aos vazamentos de dados, suas consequências e as medidas que podem ser adotadas para mitigar tais ameaças.
75 |
Riscos e ameaças Vazamentos de dados podem ocorrer de várias maneiras, incluindo ataques externos, erros humanos e falhas de segurança. Entre os riscos associados, destacam-se:
76 |
a) Roubo de identidade: Com dados pessoais e financeiros expostos, os criminosos podem assumir a identidade de um indivíduo e cometer fraudes.
77 |
b) Espionagem corporativa: Informações confidenciais sobre empresas e seus negócios podem ser usadas para vantagem competitiva por concorrentes.
78 |
c) Chantagem e extorsão: Criminosos podem exigir pagamento para não divulgar informações sensíveis ou restaurar o acesso a sistemas comprometidos.
79 |
d) Danos à reputação: Vazamentos de dados podem prejudicar a confiança dos consumidores e parceiros de negócios, levando a perdas financeiras e dificuldades em atrair novos clientes.
80 |
Consequências legais e regulatórias Governos e órgãos reguladores ao redor do mundo têm implementado políticas e leis mais rígidas para proteger a privacidade dos dados e responsabilizar as empresas pelos vazamentos. As consequências legais podem incluir multas, sanções e ações judiciais movidas por clientes afetados.
81 |
Medidas de prevenção e mitigação Para reduzir o risco de vazamentos de dados, empresas e indivíduos devem adotar medidas eficazes de segurança da informação. Algumas dessas medidas incluem:
82 |
a) Implementação de sistemas de segurança robustos: Firewalls, criptografia e sistemas de detecção de intrusão podem ajudar a proteger dados e impedir ataques.
83 |
b) Educação e conscientização dos funcionários: Treinamento regular e atualizações sobre as melhores práticas de segurança ajudam a minimizar erros humanos.
84 |
c) Políticas de gerenciamento de acesso: Controle de acesso a informações sensíveis e monitoramento de atividades suspeitas são essenciais para prevenir vazamentos.
85 |
d) Atualização e manutenção de software: Manter sistemas operacionais e aplicativos atualizados ajuda a corrigir vulnerabilidades conhecidas e a prevenir ataques.
86 |
e) Plano de resposta a incidentes: Um plano bem elaborado pode ajudar a identificar, conter e remediar rapidamente um vazamento de dados, minimizando os danos causados.
87 |
Os vazamentos de dados representam uma ameaça real e crescente na era digital. Conscientizar-se dos riscos, implementar medidas de segurança adequadas e cumprir as regulamentações são passos fundamentais para proteger informações valiosas e preservar.
88 |
89 |
90 |
91 |
A Importância de Emails Temporários
92 |
Nos dias de hoje, a segurança e a privacidade na internet são questões primordiais para os usuários. Com a crescente quantidade de informações e dados pessoais disponíveis online, é essencial encontrar maneiras de proteger a nossa identidade digital. Uma das ferramentas que pode ajudar nesse aspecto são os emails temporários. Estes serviços de email descartáveis oferecem uma alternativa para proteger a privacidade e segurança dos usuários. Neste texto, vamos explorar a importância de usar emails temporários em diversas situações.
93 |
Prevenção de spam e newsletters indesejadas Um dos principais benefícios dos emails temporários é a prevenção de spam e newsletters indesejadas. Ao utilizar um endereço de email descartável, os usuários podem evitar que suas caixas de entrada principais fiquem sobrecarregadas com mensagens não solicitadas. Quando o email temporário é usado para se inscrever em sites e serviços, todas as mensagens subsequentes são enviadas para esse endereço, poupando a caixa de entrada principal de emails indesejados.
94 |
Proteção da privacidade Outro ponto importante é a proteção da privacidade do usuário. Muitas vezes, ao nos inscrevermos em sites ou aplicativos, somos obrigados a fornecer um endereço de email. Porém, nem sempre é possível garantir a segurança das informações fornecidas. Utilizar um email temporário permite manter o endereço de email pessoal em sigilo, protegendo a privacidade e evitando que dados pessoais sejam compartilhados com terceiros.
95 |
Testes de serviços e produtos Muitas vezes, os usuários precisam testar serviços ou produtos online que exigem um endereço de email para acesso. Nesses casos, fornecer um email temporário pode ser uma opção útil e prática. Isso permite experimentar o serviço sem comprometer a segurança do endereço de email principal. Caso o usuário decida continuar utilizando o serviço após o período de teste, pode então fornecer o endereço de email pessoal.
96 |
Redução do risco de ataques de phishing Os emails temporários também ajudam a reduzir o risco de ataques de phishing. Essas tentativas de fraude ocorrem quando criminosos enviam mensagens falsas que se passam por comunicações legítimas, na tentativa de obter informações pessoais, como senhas e dados financeiros. Como os emails temporários são descartáveis e geralmente usados para fins específicos, fica mais fácil identificar tentativas de phishing e descartá-las.
97 |
Em suma, o uso de emails temporários é uma prática eficiente e inteligente para proteger a privacidade e a segurança dos usuários na internet. Ao utilizar esses serviços, podemos nos resguardar de spam, newsletters indesejadas, tentativas de phishing e compartilhamento indevido de informações pessoais. A utilização desses endereços de email descartáveis contribui para uma experiência online mais segura e agradável.
98 |
99 |
100 |
101 |
109 |
110 |
111 |
112 |
118 |
119 |
120 |
121 |
122 |
138 |
139 |
348 |
349 |
--------------------------------------------------------------------------------
/hosting/src/src/components/global/GlobalEmailForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
75 |
76 |
190 |
--------------------------------------------------------------------------------